Hacker News new | past | comments | ask | show | jobs | submit login

You can't use alloca from inside a library function, since it would allocate within the library function's stack frame and the allocation would no longer be valid when the function returned. (Or rather, you can use alloca within library functions, but you can't return a pointer to that allocation, so it wouldn't be useful here.)

Theoretically you could define an alloca()ed-pointer-returning Xsprintf as a macro, though... (but ask tptacek notes, it's probably a bad idea).




Something like this (C99; given p, stack-allocates p_sasprintf_buf of size at most 16 if the string would fit, and uses asprintf otherwise):

    #include <err.h>
    #include <stdio.h>
    #include <stdlib.h>
 
    #define SASPRINTF_MAXLEN 16
    #define SASPRINTF_MERGE(a, b) a ## b
    #define SASPRINTF_LEN(p) SASPRINTF_MERGE(p, _sasprintf_len)
    #define SASPRINTF_BUF(p) SASPRINTF_MERGE(p, _sasprintf_buf)
    #define SASPRINTF(p, fmt, ...) \
        size_t  SASPRINTF_LEN(p) = snprintf(NULL, 0, (fmt), __VA_ARGS__); \
        char    SASPRINTF_BUF(p)[SASPRINTF_LEN(p) <= SASPRINTF_MAXLEN ? SASPRINTF_LEN(p) + 1 : 0]; \
        if (SASPRINTF_LEN(p) <= SASPRINTF_MAXLEN) { \
            snprintf(SASPRINTF_BUF(p), SASPRINTF_LEN(p) + 1, (fmt), __VA_ARGS__); \
            p = SASPRINTF_BUF(p); \
        } else { \
            if (asprintf(&p, (fmt), __VA_ARGS__) == -1) \
                err(1, "SASPRINTF_L at %s, %d", __FILE__, __LINE__); \
        }
    #define SASPRINTF_FREE(p) do { \
            if (p != SASPRINTF_BUF(p)) \
                free(p); \
        } while(0)
 
    /* Test harness */
    int main(void);
 
    int main(void) {
            char *p, *p2;
    
            SASPRINTF(p, "%s", "foo");
            SASPRINTF(p2, "%s", "Really long string, really.");
 
            printf("%s\n%s\n", p, p2);
 
            SASPRINTF_FREE(p);
            SASPRINTF_FREE(p2);
 
            exit(EXIT_SUCCESS);
    }
I was going to say "...but you have to be pretty insane to do this", but I haven't managed to get incorrect-but-compiling code out of the above macros. Of course, I'm not at all convinced that it's faster than asprintf... (even after the obvious optimizations.)


This is not valid C99. In C99, arrays must have at least one element. Also, what is err.h? Whatever it is, it is not C99.

As for speed, if asprintf() does something clever to avoid rendering the string twice, this is actually slower unless snprintf() is faster than a malloc() call (unlikely). Furthermore, some compilers implement variable-length arrays with malloc() so for these, this is definitely not an improvement.

Beyond the speed of this particular call, using variable-length arrays can have a performance hit in general since gcc is unable to inline functions using them.


That's a good point - I can see why they wouldn't exactly want to encourage macro hacks at this point.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: