What is a good way to allocate a string size buffer on the stack?


Using pure C (and the C-preprocessor) I would like to create a string buffer that includes a length parameter, so that I could pass it around easily and any functions that operate on it could do so without danger of writing past the end. This is simple enough:

typedef struct strbuf_t_ {
    int  length;
    char str[1];
} strbuf_t;

but then if I want a small scratch space on the stack to format some output text, there is no trivial way to allocate a strbuf_t on the stack. What I would like is some clever macro that allows me to do:

STRBUF(10) foo;
printf("foo.length = %d\n", foo.length); // outputs: foo.length = 10
strncpy(foo.str, "this is too long", foo.length);

Unfortunately I don't seem to be able to do that. The best I've come up with is:

#define STRBUF(size, name) \
    struct {\
        strbuf_t buf;\
        char space[size - 1];\
        char zero;\
    } name ## _plus_space_ = { .buf={.length=size}, .space="", .zero='\0'};\
    strbuf_t *name = &name ## _plus_space_.buf

int main(void)
    STRBUF(10, a);

    strncpy(a->str, "Hello, world!", a->length);
    printf("a->length = %d\n", a->length); // outputs: a->length = 10
    puts(a->str); // outputs: Hello, wor

This meets all of the requirements I listed, but a is a pointer not the structure itself, and the allocation is certainly not intuitive.

Has anyone come up with something better?

I think you are already pretty close to a solution. Just keep a char* in your struct and allocate it via char-array. In order to have the save trailing zero at the end of string, just allocate an extra char additional to the size and initialize the whole array with zeroes.

typedef struct
    int length;
    char* str;
} strbuf_t;

#define STRBUF(varname, size) \
    char _buffer_ ## varname[size + 1] = {'\0'}; \
    strbuf_t varname = { size, _buffer_ ## varname }

int main()
    STRBUF(a, 10);

    strncpy(a.str, "Hello, world!", a.length);
    printf("a.length = %d\n", a.length);