0

I am having a problem passing a non const 2D array of pointers as const argument for a function. But I am getting an error. I don't understand why.

// Online C++ compiler to run C++ program online
#include <iostream>

void test(const int  *arrayPtr[][10]){}
//void test(int  * const arrayPtr[][10]){//Works DO NOT USE //}

int main() {
 int *arrayPtr[10][10] = {};
 test(arrayPtr);
 std::cout <<"done" << std::endl;
 return 0;
}

g++ /tmp/JYRlXRFoja.cpp /tmp/JYRlXRFoja.cpp: In function 'int main()': /tmp/JYRlXRFoja.cpp:11:7: error: cannot convert 'int* (*)[10]' to 'const int* (*)[10]'    11 |  test(arrayPtr);
      |       ^~~~~~~~
      |       |
      |       int* (*)[10] /tmp/JYRlXRFoja.cpp:5:42: note:   initializing argument 1 of 'void test(const int* (*)[10])'
    5 | void test(const int                     *arrayPtr[][10]){
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
Hani Gotc
  • 840
  • 11
  • 24
  • 1
    Remove the const from the function signature? – nicomp Feb 08 '21 at 14:02
  • The `const` in `const int *arrayPtr[][10]` is for the *return type* of the function pointers. Note the use of parentheses in the compilers error message and it will give you a hint as to which pointer needs to be `const`. – Some programmer dude Feb 08 '21 at 14:03
  • 1
    If you are using `C++` I would recommend using `std::array`. And to better understand your problem you can try your `C`-compatible array-pointer definitions in https://cdecl.org/ – Simon Kraemer Feb 08 '21 at 14:07
  • For future reference: https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion – Hani Gotc Feb 08 '21 at 18:01

1 Answers1

1

There are two errors in your code.

  1. Your passing in a int* array[][], not a const int* array[][]. So change the function parameter to int* array[][10].
  2. You are subjected to array decay. To resolve this, you should pass in the array by reference. To this your function parameter should be like this: int* (&arrayPtr)[][10].

Your error is self explanatory, it says what's wrong. If you read it carefully, it says that your passing int* (*)[10] to a const int* (*)[10] type container.

D-RAJ
  • 3,263
  • 2
  • 6
  • 24
  • 1
    But we can add `const` to the pointed to type, we can call `void foo(const char *)` with a `char *`. Why not here? – mch Feb 08 '21 at 14:10
  • @mch Nope, you cant pass a variable of type `char*` to a parameter type of `const char*`. – D-RAJ Feb 08 '21 at 14:12
  • @mch `const` is applied from right to left. `const char*` and `char const*` are identical with the first version just being more convenient (pointer to const char). `char * const` on the other hand is a `const point to char`. – Simon Kraemer Feb 08 '21 at 14:15
  • @SimonKraemer sure, so why can I add `const` to `char *a`, but not to `int *a[][10]`, but it seems that `void test(const int * const arrayPtr[][10]){}` again works? – mch Feb 08 '21 at 14:17
  • @mch Sorry, got your question wrong. Never thought of that... – Simon Kraemer Feb 08 '21 at 14:17
  • @mch In `char buffer[] = "this is a test"`, `char buffer[]` is the same as `char*`, not `const char*`. Mark it as `const char buffer[]` and you'll get the error. – D-RAJ Feb 08 '21 at 14:18
  • @D-RAJ sure, then it will fail at `char *tmp =buffer;` if `buffer` is a `const char []`, because it would remove the `const`, but why does it not work when adding the `const`? – mch Feb 08 '21 at 14:19
  • 3
    @mch `a pointer to unqualified type can be converted to a pointer to const; ` See `Qualification conversions` https://en.cppreference.com/w/cpp/language/implicit_conversion – Simon Kraemer Feb 08 '21 at 14:24
  • 1
    @SimonKraemer yes, so `int *` can be converted to `const int *`. So, why cannot `int * a[][]` be converted to `const int *b[][]`? – mch Feb 08 '21 at 14:27
  • 5
    @mch The array in this question is spurious; the underlying question is why `int*` converts to `int const*` but `int**` doesn't convert to `int const**`. Simple: `int *p; int const **q = &p /* bad conversion */; int const i = 0; *q = &i /* uh oh */; *p = 1 /* modification to i? */;` Therefore the conversion must not be allowed. – HTNW Feb 08 '21 at 14:31
  • I would assume it is because the conversion does not apply here. `int ** a` and `const int ** b`. `a`is a non-const pointer to a non-const (pointer to non-const int). `b` is a non-const pointer to a non-const (pointer to const int). The inner types are both non-const pointers to different types. – Simon Kraemer Feb 08 '21 at 14:31
  • @mch I used array decay and only 2 levels of pointers for better visibility. Also let's not be three-star-programmers. – Simon Kraemer Feb 08 '21 at 14:33
  • 1
    @HTNW thanks, that's the reason I was looking for. – mch Feb 08 '21 at 14:35
  • 1
    https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion – Hani Gotc Feb 08 '21 at 18:01