0

I'm getting warning C4047: 'int (*)[9]' differs in level of indirection from 'int **' on the line when the nineinput() function returns arr.

I don't know why it is popping this error.

Could someone explain to me the reason?

int main() {
  int(* ninearr)[9];
  ninearr = nineinput();
  GCDinput(ninearr);
  free(ninearr);
  return 0;
}

int(* nineinput())[9] {
  int i, j, a, b, tmp, res, len;
  int ** arr;

  // (...)

  len = b - a + 1;
  arr = (int **)malloc(sizeof(int *) * len);

  for (i = 0; i < len; i++) {
    arr[i] = (int *)malloc(sizeof(int) * 9);
  }

  // (...)

  return arr;
}
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Gamjago
  • 13
  • 3
  • Gamjago, you are getting this warning because what you declared that your function is going to return (a `int (*)[9]`, whatever that is) is not what the code then does return (a pointer to pointer to int, `int **arr;`). I suspect that you are not clear about what your code is declararing and implementing. So you should probably explain in detail what you mean your code to do. Especially each one of the lines `int (*ninearr)[9]; ninearr = nineinput(); ninearr = nineinput();` , the number of `free()`s in contrast to the number of `malloc()`s, the calculation of the malloced sizes, ... – Yunnosch Jul 05 '21 at 06:18
  • ... the meaning of each of your `9` occurrences. And since not everything you are referencing is defined or even declared in your code, you should provide a [mre]. – Yunnosch Jul 05 '21 at 06:19
  • This is a great tool for understanding how a C compiler reads your declarations https://cdecl.org – Yunnosch Jul 05 '21 at 06:23
  • @Yunnosch Thank you, Yunnosch. Frankly, I don't have much knowledge about this pointer thing. The reason why I thought this would work is, I saw somewhere from the internet that to return 2 dimensional array, you have to use int(*ReturnArray())[ARR_COL_SIZE] kind of form. And to make 2 dimensional array but with user's input for length of row/column, you have to use malloc function. So, I thought, maybe (*ninearr)[9] and arr will have the same form, with the same column size of 9. But clearly, it seems not working. – Gamjago Jul 05 '21 at 06:42
  • @Yunnosch Anyway, here is what I was going to do: run nineinput and return arr to use it as argument of GCDinput. I put free() just to see if it make any difference. – Gamjago Jul 05 '21 at 06:42
  • Yes and no. You have to do several things consistently. Have a look here: https://stackoverflow.com/questions/68251484/can-double-pointers-be-used-as-2d-arrays And with pointers you need to be very careful, because they are a very flexible and even more powerful tool. Most of the uses of pointers are handy for shooting your own foot. Better find a set of incremental tutorials, and a book. Yes, both. – Yunnosch Jul 05 '21 at 06:46

2 Answers2

0

The warning here says that you are lying to the compiler. A pointer to array of size 9 is used when you want to process a true 2D array of n rows of 9 columns. Said differently all rows have to be contiguous.

But what you build is actually a array of pointers. You have no guarantee that your rows are contiguous and future index computations are likely to be wrong.

Arrays of pointers and 2D (contiguous) arrays are different animals. Choose your horse and stick to it...

(more references about that at Correctly allocating multi-dimensional arrays).

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

An array pointer int(* ninearr)[9]; cannot be used to point at a pointer-to-pointer. It must be used to point an array. Your malloc calls in the functions do not allocate a 2D array, but an array of pointers. See Correctly allocating multi-dimensional arrays for details.

The easiest way to fix your function is:

int(*nineinput(void))[9]
{
  // ...
  int(*arr)[9] = malloc( sizeof(int[len][9]) );
  // ...
  return arr;
}

Alternatively, return through a parameter:

void nineinput (int (**arr)[9])
{
  // ...
  *arr = malloc( sizeof(int[len][9]) );
  // ...
}

Although since the syntax is quite evil in both of these cases, it could in some cases be acceptable to just to do void* nineinput (void) and discard type safety for readability.

Lundin
  • 195,001
  • 40
  • 254
  • 396