7

I looked at couple of instances wherein I see something like char fl[1] in the following code snippet. I am not able to guess what might possibly be the use of such construct.

struct test
{
    int i;
    double j;
    char fl[1];
};

int main(int argc, char *argv[])
{
    struct test a,b;
    a.i=1;
    a.j=12;
    a.fl[0]='c';

    b.i=2;
    b.j=24;
    memcpy(&(b.fl), "test1" , 6);
    printf("%lu %lu\n", sizeof(a), sizeof(b));
    printf("%s\n%s\n",a.fl,b.fl);
    return 0;
}

output -

24 24 
c<some junk characters here>
test1
4
  • 1
    The purpose here seems to just overwrite random parts of the stack, but usually a trailing one-element array is a sign of the struct hack. Commented Jan 30, 2013 at 16:46
  • Its called a flexible array. It allows you to allocate/use memory for the structure plus additional buffer space addressable from the last member (in this case, a char[]). If improperly used, it can be an equitable source of both confusion, and bugs. (this would be an excellent example of that, btw). Commented Jan 30, 2013 at 16:46
  • @WhozCraig That's not a flexible array member, though it seems to be used in place of one. Commented Jan 30, 2013 at 18:08
  • @modifiablelvalue yeah, i just caught the [1] after posting. My dyslexia always seems to skip over '1' when sitting next to ']'. Strangly, not '['. Think its the top of the char that does it. Good point, though. Thanks for pointing it out. Commented Jan 30, 2013 at 18:34

3 Answers 3

6

It's called "the struct hack", and you can read about it at the C FAQ. The general idea is that you allocate more memory then necessary for the structure as listed, and then use the array at the end as if it had length greater than 1.

There's no need to use this hack anymore though, since it's been replaced by C99+ flexible array members.

Sign up to request clarification or add additional context in comments.

3 Comments

+1. With the prevalence of usage of this, I'm amazed it took so long to add to the standard.
C99 is almost 15 years old. What surprises me is how some vendors still don't support it!
I concur. It was the 10 before (C90) that surprises me. And absolutely, even now, 25 years later, to not support this is ludicrous.
0

The idea usually is to have a name for variable-size data, like a packet read off a socket:

struct message {
    uint16_t len; /* tells length of the message */
    uint16_t type; /* tells type of the message */
    char payload[1]; /* placeholder for message data */
};

Then you cast your buffer to such struct, and work with the data by indexing into the array member.

Comments

0

Note that the code you have written is overwriting memory that you shouldn't be touching. The memcpy() is writing more than one character into a one character array.

The use case for this is often more like this:

struct test *obj;
obj = malloc(sizeof(struct test) + 300); // 300 characters of space in the
                                         // flexible member (the array).
obj->i = 3;
obj->j = 300;
snprintf(obj->f, 300, "hello!");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.