tags:

views:

2494

answers:

5

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 :).

+3  A: 

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] ...
Paul Beckingham
Well, that would make each element of the main array of size 13. What if I want to have pointers to arrays of different sizes? As for char - char can be used for small integer values, so it's not a problem here.
Ree
If you specify the second dimension, the first is then defined through an initializer list.
Paul Beckingham
Sorry, your answer is not related to my initial comment. If I do what you say, "that would make each element of the main array of size 13". What I'm after is initializing an array of pointers to arrays of DIFFERENT sizes.
Ree
You can't assign to arbitrarily sized dimensions - that takes Perl and its ilk. I was showing you *one* limited way in which you can solve the "this doesn't" part of your question.
Paul Beckingham
+2  A: 

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.

Greg Rogers
Nope. If you specify the second dimension, the first can be left [], so your example /char a[][12] = {"hello", "world"};/ is legal.
Paul Beckingham
The first example is perfectly legal - I don't need to create explicit pointers to the strings. However, the problem is the SECOND example.
Ree
Why can I leave them both blank in the first example, but not the second? String literals are arrays and I have arrays in the second example as well?
Ree
Now that you have edited your answer, things are much more clear now. Thank you.
Ree
A: 

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;
}
Pete Kirkham
A: 

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.

aib
It is fine to assign `char *foo = "Hello World";` You do not need a const.
Raim
Yes, const is not needed.
Ree
fine, editing...
aib
A: 

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.

André Bergner
OK, but the question is strictly C related (see tags), so it would have been better if your example didn't contain C++ code.
Ree
It's also not exactly the same. I was looking for the same problem, but I need the arrays to be named.
Marco van de Voort