2

Just learning C, so bear with me. I understand that char *argv[] is an array whose elements are pointers to strings. So, for example:

char *fruits[] = {"Apple", "Pear"};

represents a "ragged array" of char arrays (i.e. a two-dimensional array whose rows have different lengths). So far, so good.

But when I try to abstract this to int types, it does not seem to work.

int *numbers[] = { {1,2,3}, {4,5,6} };

I get the following warning from the GCC compiler:

warning: braces around scalar initializer.

Can someone help me wrap my brain around this?

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 3
    "Ragged array" isn't a thing. This just an array of pointers to other things. This is not to be confused with an actual 2D array since the memory layout is completely different. 2D arrays are contiguous. Arrays with pointers in them can point to *anywhere*. – tadman Jan 04 '23 at 18:08
  • 1
    Would `int numbers[][]` work for you here? – tadman Jan 04 '23 at 18:09
  • 2
    You can declare it this way: `int *numbers[] = { (int[]){1,2,3}, (int[]){1,2,3} };` – jvx8ss Jan 04 '23 at 18:10
  • 2
    Note that unlike strings, which are terminated by a null character, those compound literals don't have any way to tell the lengths. – Barmar Jan 04 '23 at 18:13
  • @jvx8ss May I ask what type `{1,2,3}` is before the casting? – mkdrive2 Jan 04 '23 at 18:14
  • @mkdrive2 `(int[]){...}` is an unnamed array of integers. https://en.cppreference.com/w/c/language/compound_literal – jvx8ss Jan 04 '23 at 18:18
  • 1
    @mkdrive2 it is integer :) – 0___________ Jan 04 '23 at 18:27
  • @0___________ Why is it a single integer, even though there are multiple numbers? – mkdrive2 Jan 04 '23 at 18:29
  • 1
    @mkdrive2 because it is simple comma operator https://godbolt.org/z/9ss9zP3q5 – 0___________ Jan 04 '23 at 18:32
  • A "ragged array" is a well-defined concept. I am confused how everyone is giving OP grief over it: using an array of pointers is _literally_ the only way to implement a radded array in C... – Dúthomhas Jan 04 '23 at 19:07
  • Thanks @Dúthomhas. I thought from the textbook that I was reading that "ragged array" was the most descriptive way to say what I was trying to accomplish. Turns out I had the concept right in my head; I was just initializing it incorrectly. Thanks 0___________ and jvx8ss for pointing me to compound literals to use in the initialization. Much appreciated! – Jeff Favret Jan 04 '23 at 21:20

2 Answers2

3

int *numbers[] = { {1,2,3}, {4,5,6} } can't work, you are attempting to initialize elements of an array of pointers with lists of integers.

To initialize an array of pointers you need to provide the addresses that point to the desired values, i.e. you must initialize each element of the pointer array with addresses of the ints you want them to point to, in this case the initial element of an array of int so that you can have access to the beginning of the array and thus to the rest of it via indexing:

//have 2 flat arrays of int
int a[] = {1, 2, 3};
int b[] = {4, 5, 6};
// make the array of pointers point to its initial elements
int *numbers[] = { &a[0], &b[0] };
// access
printf("%d", numbers[1][1]); // 5

You could also use:

int *numbers[] = { a, b };

Why? Because when you use an array name in an expression, for example you pass it as argument of a function or an initializer list like the above one, it decays to a pointer to its first element.

char *fruits[] = {"Apple", "Pear"}; works fine because string literals have type char[] generally, e.g. "Apple" has type char[6], so when you use them in the initializer list expression the same decay process occurs, and you'll end up with a pointer to the first element of the nul terminated array of chars.

Note that unlike the above string literals (which all end with a nul byte \0), the int arrays have no sentinel value, unless you establish one, otherwise for you to safely navigate inside the bounds of each array you must keep track of its size.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • @anastaciu - one more query re: your final point (no sentinel value): How do developers generally track the size of each array in their code? Would you use a struct with a counter component and an integer array component? – Jeff Favret Jan 04 '23 at 23:13
  • @JeffFavret that would be a good solution, yes. – anastaciu Jan 05 '23 at 01:27
1

int *numbers[] It is not "ragged array" only an array of pointers.

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

In this example it has two elements having type pointer to int. Those pointers hold the reference of the first element of the arrays used to initialize it.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • Why does `(int[])` work and `(int *)` doesn't if both are pointers? – mkdrive2 Jan 04 '23 at 18:22
  • No, there arrays and pointers are something completely differentg – 0___________ Jan 04 '23 at 18:27
  • Arrays are different from pointers, until they are not. When passing an array to a function for example, the array decays into a pointer. That doesn't mean a pointer is an array. – Marco Jan 04 '23 at 18:35
  • Then is it not so that `(int[])` makes `{1,2,3}` to an array rather than a pointer? – mkdrive2 Jan 04 '23 at 18:40
  • 1
    @mkdrive2 `(int[])` is not a pointer. that's why `sizeof((int[]){1,2,3,4})` returns 16 instead of 8 – jvx8ss Jan 04 '23 at 18:54
  • @marco-a - sorry but I think you do not understand it. Arrays decay to pointers in **expressions**. But array and pointer are completely different – 0___________ Jan 04 '23 at 18:55
  • @jvx8ss Do I understand it right that by initializing `*numbers[]` like that, the same thing happens as if the array was given to a function as an argument and degenerates into a pointer? – mkdrive2 Jan 04 '23 at 19:11
  • @0___________ I understand very well. I said pointers aren't arrays, but arrays sometimes behave like pointers, that doesn't make array pointers though. – Marco Jan 04 '23 at 19:12
  • 1
    @mkdrive2 they do not "degenerate", they decay to pointers (but only as rvalues) in expressions. Read more about it: https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay – 0___________ Jan 04 '23 at 19:16