Question

This example works fine:

static char *daytab[] = {
    "hello",
    "world"
};

This doesn't:

static char *daytab[] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

The way I see it is that the first example creates an array that is filled with pointers to the two string literals (which themselves are arrays). The second example, IMO, should be identical - create an array and fill it with pointers to the two char arrays.

Could someone explain to me why the second example is wrong?

P.S. You could probably write it like this (haven't tested it):

static char a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char b[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char *daytab[] = {
    a,
    b
};

But that looks like too much work :).

Was it helpful?

Solution

This:

{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

Is just an array initializer. It doesn't itself create an array. The first example, when you assigned a string literal to a pointer, DID create those strings in static storage (hidden to you), and then just assigned the pointers to them.

So basically, there is no way to initialize your char* with the array initializer. You need to create an actual array, and assign those numbers to it. You would have to do something like:

char a[][] = { {32, 30, 0}, {34, 32, 33, 0} }; // illegal

But that is illegal.

You need to build the array separately and assign them into an array like your last example.

OTHER TIPS

Try:

static char daytab[][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

Those aren't char*'s. They aren't char either. You probably want:

static int daytab[][13] ...

Well, this thread is already a bit old, however I was dealing with the same problem and found a way to initialize an array of pointers to arrays, like this:

#include <iostream>
using namespace std;

int *a[] = {
  (int[]) { 0 } ,
  (int[]) { 1 , 2 } ,
  (int[]) { 3 , 4 , 5 } ,
  (int[]) { 6 , 7 , 8 , 9 }
};

main()
{
  cout
  << a[0][0] << endl
  << a[1][0] << " " << a[1][1] << endl
  << a[2][0] << " " << a[2][1] << " " << a[2][2] << endl
  << a[3][0] << " " << a[3][1] << " " << a[3][2] << " " << a[3][3] << endl;
}

And I get the output, compiling with gnu g++

0
1 2
3 4 5
6 7 8 9

and compiling with intel icpc

0
1 1
40896 32767 -961756724
0 32767 4198878 0

So, the syntax seems to be in principle correct, just that the intel compiler does not correcly support it, probably due to a lack of common use of this style.


--- edit ---

Here is also a C version (as demanded):

#include <stdio.h>

int *a[] = { 
  (int[]) { 0 } , 
  (int[]) { 1 , 2 } , 
  (int[]) { 3 , 4 , 5 } , 
  (int[]) { 6 , 7 , 8 , 9 } 
};

int main()
{
  printf( "%d\n" , a[0][0] );
  printf( "%d %d\n" , a[1][0] , a[1][1] );
  printf( "%d %d %d\n" , a[2][0] , a[2][1] , a[2][2] );
  printf( "%d %d %d %d\n" , a[3][0] , a[3][1] , a[3][2] , a[3][3] );
}

I tested it with gcc and clang and it prints the correct result. Btw. the wrong output of the intel compiler was a compiler bug.

static char **daytab;
daytab=(char**)malloc(2*sizeof(char*));
daytab[0]=(char*)(char[]){0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
daytab[1]=(char*)(char[]){0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

The syntax of your second example is the syntax for a multidimensional array literal.

A multidimensional array is not an array of pointers to arrays.

It would be surprising if the syntax for one thing was also the syntax for a different thing, depending on the type it is declared to be.

In the first example, because a string literal is evaluated to a pointer rather than an array value, the value is evaluated as an array of pointers. Because an array literal is evaluated as an array value rather than a pointer, the second example is a multidimensional array - an array whose elements are array values, not an array whose elements are pointers to array values.

The following code demonstrates the combinations of multidimensional arrays, pointers to arrays, arrays of pointers, and pointers to pointers. Of these three, only arrays of pointers and pointers to pointers are compatible with each other:

void multi_array (int x[][4], size_t len) // multidimensional array
{
    for (size_t i = 0; i < len; ++i)
        for (size_t j = 0; j < 4; ++j)
            putchar( 'a' + x[i][j] );
    putchar('\n');
}

void ptr_array (int (*x)[4], size_t len) // pointer to an array
{ ... as multi_array  }

void array_ptr (int *x[], size_t len) // array of pointers
{ ... as multi_array  }

void ptr_ptr (int **x, size_t len) // pointer to pointer
{ ... as multi_array  }

int main() {
    int a[][4] = { { 1,2,3,4 } };
    int b[] = { 1,2,3,4 };
    int* c[] = { b };

    multi_array( a, 1 );
    multi_array( (int[][4]) { { 1,2,3,4} }, 1 ); // literal syntax as value
    ptr_array( &b, 1 );
    array_ptr( c, 1 );
    ptr_ptr( c, 1 ); // only last two are the same

    return 0;
}

Note that your first example doesn't work, either. It needs to be:

static const char *daytab[] = {
    "hello",
    "world"
};

Note the const.

Edit: And by "doesn't work", I mean bad practice and prone to errors, which is arguably worse.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top