Home > Software engineering >  G responds differently to const int** and const int* as function parameters
G responds differently to const int** and const int* as function parameters

Time:10-09

I was writing a C function that takes int** as input and the function itself does not modify the data (i.e. matrix elements). So I decided to make the argument a const int** type (Is that an acceptable practice?). A sample code is like this:

void func1(const int* k) {
    std::cout << *k << '\n';
}
void func2(const int** k) {
    std::cout << **k << '\n';
}
int main() {
   int m = 0;
   int* p1 = &m;
   func1(p1);
   int** p2 = &p1;
   func2((const int**)p2); // compilation error unless explicit type conversion
   // func2(p2); /* [*] compilation error */
   (**p2)  = 1;
   func1(p1);
   func2((const int**)p2);
   return 0; 
}

My question is, when calling func2, I have to explicitly convert the double-pointer p2 to const int**, otherwise it gives the following error:

 error: invalid conversion from ‘int**’ to ‘const int**’ [-fpermissive]

Whereas func1 has no such issue. I tested this with both g (10.2.0) on Cygwin and Intel's icpc. Could someone explain why the compiler behaves this way and what is a good practice in this situation?

CodePudding user response:

In a sense, having a const int ** is saying "this pointer points to a pointer to an integer that won't be modified". The problem with implicitly casting an int ** to const int ** is that that promise is easy to mistakenly not keep. For example:

const int c = 1;
int *p1;
const int **p2 = &p1;   /* implicit cast from int** to const int** */
*p2 = &c;               /* change what the pointed-to pointer points to */
*p1 = 2;                /* change a value pointed to by a const int** */

So the requirement for an explicit cast is to make you think about this, I guess.

Example adapted from here.

CodePudding user response:

With multiple levels of pointers, a type is only more const-qualified if every level of pointer from the right has const added. This is for const-correctness reasons so that when you assign to the pointer, you can't accidentally assign a more const-qualified pointer at the "lower" levels of pointers when you have multiple pointers.

For example:

int ***     *     *     * i;
int ***const*const*const* j = i;
    // ^ All levels after this have to be const-qualified

This includes the left-most type, const int. So, if your data is not modified, you should have int const* const* k.

This is the case in C (as a qualification conversion), but this is still allowed implicitly in C because all pointers can be implicitly converted.

  • Related