0

This probably sounds like a previously asked question - there are a bunch of questions out there about the difference between arrays and pointers in C, but none of them provide quite enough information to answer this question.

I know that the name of a C array is treated by the C compiler like a pointer to the start of the memory block, but when I try to assign the name of a 3 x 3 2D array of ints to an int ** in my CLION IDE, it highlights the assignment and says:

Incompatible pointer types 'int * *' and 'int [3][3]'

int x[3][3];
int **px = x;  <-- warning here

I can cast the assigned value to (int**) and the highlight goes away of course, but - hey - you can cast a helluva lot of stuff in C and get highlights to go away. Doesn't mean what you're asking for is going to work.

Is this just a CLION (or, probably more appropriately, clang tidy) problem, or is a real issue?

[edit]

For some context, the problem with all the other answers on array/pointer differences is that many of them say things like "because an 3x3 array is not a int **, that's why!" Thanks, but that's a fairly useless piece of information - the person asking the question likely already knows a 3x3 array is not an int ** - the question is how does the compiler treat the resulting int ** after the assignment - will it properly index the array or not?

John Calcote
  • 793
  • 1
  • 8
  • 15
  • Could you post the line in question? – SIGSTACKFAULT Oct 19 '17 at 16:22
  • 4
    A 2d array is **not** an array of pointers, that's why. –  Oct 19 '17 at 16:22
  • 1
    An `int**` is a sequential list of `int*`; an `int[3][3]` is a sequential list of 3 sequential lists of 3 ints. `int[]` decays to `int*` by resolving to the address of the first element of the array, but that can't work transitively. – zneak Oct 19 '17 at 16:23
  • "or is a real issue?" Quite real. The message explains. – DeiDei Oct 19 '17 at 16:23
  • Nothing real in this bullshit warnings :) – Anton Malyshev Oct 19 '17 at 16:26
  • assign it to the correct type of pointer (a pointer to a 3-element array of `int`) like e.g. `int array[3][3]; int (*x)[3] = array;`. –  Oct 19 '17 at 16:27
  • 1
    Here's a [related answer](https://stackoverflow.com/a/46489359/2371524). –  Oct 19 '17 at 16:31

1 Answers1

2

While someone can correct me on this one multidimensional array may not be and usually is not implemented as array of pointers, it's contiguous piece of memory with some syntaxic sugar on top of it for dereferencing.

See this for details.

orhtej2
  • 2,133
  • 3
  • 16
  • 26
  • Thanks @orhtej2 - don't know how I missed that answer - it perfectly answers my question. – John Calcote Oct 19 '17 at 16:37
  • Yes, but that "syntactic sugar" makes it to be compatible with `int **` – Anton Malyshev Oct 19 '17 at 16:45
  • @AntonMalyshev can I see how? The link I provided suggests otherwise. – orhtej2 Oct 19 '17 at 16:51
  • @AntonMalyshev after reading the provided link, I now understand how an int ** cannot be used to properly reference an int array[3][3]. An int ** is a pointer to an array of pointers, while an int \*array[3] is a pointer to an array of 3-integer objects. Assuming a pointer is 8 bytes wide, and 3 integers are 3 x 4 or 12 bytes wide, it makes no sense to assume the compiler will properly index an int** pointer into the array of 3-int objects, even with a type cast. – John Calcote Oct 19 '17 at 16:57
  • A multidimensional array in fact can not ever be implemented as an array of pointers, it isn't optional, so we can do better than "usually is not". Each successive dimension must be implemented as a contiguous array of arrays. – Crowman Oct 19 '17 at 18:28
  • @JohnCalcote: `int *array[3]` is actually an array of three elements of type pointer-to-`int`. `int (*array)[3]` would be a pointer to an array of three elements of type `int`. – Crowman Oct 19 '17 at 18:29
  • @AntonMalyshev: The two are absolutely not compatible. Consider `int a[4][4] = {0};` This will give you, assuming 32-bit `int`s, a 64-byte block of memory with all bits set to zero. If you point `int ** p` at that, `p[0]` will be a null pointer, and `p[0][0]` will give you a segmentation fault. – Crowman Oct 19 '17 at 18:40
  • Yes, indeed. Sorry for my erroneous comments! – Anton Malyshev Oct 19 '17 at 18:46
  • @PaulGriffiths - thank you for that correction - you're absolutely correct - there have been a lot of comments around here lately that int *array[3] is just another notation for int array[][3]. – John Calcote Oct 21 '17 at 06:59