Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array initialization [c/c++]

Tags:

c++

c

Why this is not allowed?

#include <cstdio>

struct Foo {
int fooId;
char arr[ ];
} fooList[] =
{ {1, {'a', 'b'}},
  {2, {'c', 'd'}}
};

int main()
{
  for (int i = 0; i < 2; i++)
    printf("%d %c\n", fooList[i].fooId, fooList[i].arr[0]);
}

whereas, this is allowed:

struct Foo {
int fooId;
char arr[2]; // this line modified
} fooList[] =
{ {1, {'a', 'b'}},
  {2, {'c', 'd'}}
};
like image 252
sud03r Avatar asked Dec 05 '22 23:12

sud03r


2 Answers

Only the last member of a C struct can be flexible as in arr[].

Shamelessly copying from paragraph 6.7.2.1, sub-paragraph 16 of the ISO C99 standard:

16 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. With two exceptions, the flexible array member is ignored. First, the size of the structure shall be equal to the offset of the last element of an otherwise identical structure that replaces the flexible array member with an array of unspecified length.106)...

EDIT:

As for C++, see this. Bottom-line: flexible array members are not allowed in C++ at all - at least for the time being.

like image 54
thkala Avatar answered Dec 09 '22 14:12

thkala


In C++ all members of an user defined type must have complete types, and the member arr does not have a complete type unless you give it a size.

In C, the struct definition would compile, but you might not get what you want. The problem is that an array without size is allowed at the end of a struct to be used as a proxy to access the contiguous block of memory after the instance. This allows a dumb vector implementation as:

typedef struct vector {
   int size;
   char buffer[];
} vector;
vector* create_vector( int size ) {
   vector* p = (vector*) malloc( sizeof *p + size ); // manually allocate "size" extra
   p->size = size;
};
int main() {
   vector* v = create_vector(10);
   for ( int i = 0; i < v->size; ++i )
      printf("%d\n", v->buffer[i] );
   free(v);
}

But the language does not allow you to initialize with the curly braces as the compiler does not know how much memory has to be held (in general, in some circumstances it can know). The size-less member of the struct is only a way of accessing beyond the end of the object, it does not hold memory in itself:

printf( "sizeof(vector)=%d\n", sizeof(vector) ); // == sizeof(int)
like image 29
David Rodríguez - dribeas Avatar answered Dec 09 '22 14:12

David Rodríguez - dribeas