views:

191

answers:

5

I don't understand why

struct e{
    void * a;
    void * b[];
}

has sizeof(e) == 4 while

struct f{
    void * a;
    void * b;
}

has sizeof(f) == 8.

+16  A: 
KennyTM
Does that mean i can't access it?
Alan J.
@Alan: No, you can still access `b`.
KennyTM
@Alan: no; it just means that sizeof() returns the result you observe.
Jonathan Leffler
@Alan: Yes. You need a C99 compiler, and you need to allocate space for the structure beyond the `sizeof` the structure. If you put it on the stack accessing it will be UB.
Billy ONeal
By your comments and the "sizeof" entry on Wikipedia i now grasp it. Thanks!
Alan J.
+11  A: 

The second in the first struct is not a pointer, but a FAM - flexible array member. It is used when you have a long buffer and place an e at the start of that buffer. You can then index the remaining memory that follow the e object using that FAM and treat that memory as an array of void*.

The Standard says (emphasis by me)

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.

For example, the following code outputs 1 for the struct without, but 4 for the struct with the FAM on GCC, because to access integers the FAM need to be properly aligned (on a 4 byte boundary in this example)

struct A {
  char a;
};

struct B {
  char a;
  int flex[];
};

int main() {
  printf("sizeof A: %d\nsizeof B: %d\n", 
         (int)sizeof(struct A),
         (int)sizeof(struct B)
    );

  struct B *b = malloc(sizeof *b + sizeof(int[3]));
  b->a = 'X';
  b->flex[0] = 1;
  b->flex[1] = 2;
  b->flex[2] = 3;
  free(b);
}
Johannes Schaub - litb
Since you compiled the contents in various posts and added an example, i accepted your answer over the previous one.
Alan J.
+2  A: 

This is because the second struct uses a flexible member array. Explanation of the sizeof result is in in Wikipedia.

Alexandre C.
+1  A: 

void * b[]; is invalid in C89, so it means you're using a C99 compiler.

C99 introduced a means to define the "struct hack": it's now called "flexible array member" and before it is allocated memory, its size is 0.

pmg
This is was also important to note because i was trying to stick with C89. Thanks!
Alan J.
A: 

Because the first isn't declaring any space for the pointers in "b".

fortran