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
Shraddha
  • 2,427
  • 5
  • 17
  • 21
  • 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](http://stackoverflow.com/questions/3711233/is-the-struct-hack-technically-undefined-behavior). – Fred Foo Jan 30 '13 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). – WhozCraig Jan 30 '13 at 16:46
  • @WhozCraig That's not a flexible array member, though it seems to be used in place of one. – autistic Jan 30 '13 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. – WhozCraig Jan 30 '13 at 18:34

3 Answers3

7

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.

Community
  • 1
  • 1
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
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.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
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!");
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173