Hairi Hairi - 2 months ago 8
C Question

How are these two definitions different to the compiler?

This statement is correct:

char *c[3] = {"abcd", "efgh", "jklm",};


This one though is structurally similar, but the compiler doesn't like it.

int *a[3] = {{48,49,50,51}, {5,6,7,8}, {9,10,11,12},};


How do they differ? Can't the compiler infer the size from the initialization of
a
?

It seems to me that the compiler treats the
char *
different.

Answer

Unlike C string literals, which produce a null-terminated array that "decays" to a pointer. In order to get the same functionality with integers, you need to use compound literals.

C compiler will allocate memory for "abcd" and its null terminator, and give you the pointer. However, the compiler will not allocate memory for an array of integers {48,49,50,51} unless you tell it that the literal represents an array of integers:

int *a[3] = {
    (int[]){48,49,50,51}
,   (int[]){5,6,7,8}
,   (int[]){9,10,11,12}
};

This functionality is available in C99 and newer. If you are using an older compiler, and would like your a[] to be an array of pointers, you need to allocate its elements separately:

static int a0[] = {48,49,50,51};
static int a1[] = {5,6,7,8};
static int a2[] = {9,10,11,12};
int *a[] = {a0, a1, a2};

This lets you make a "jagged" array. If you do not want a jagged array, because all rows in a[] have the same size of 4, you can create a regular 3x4 array instead.