Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Difference between const pointer and const array type in function parameter declaration

If I try to compile this small example:

void f(const int *a) {
    int * ptr = a;
    *ptr = 1;
}

void g(const int a[]) {
    int * ptr = a;
    *ptr = 1;
}

I get a warning for function f and an error for function g. I tried with gcc 9.3.0 and clang 10.0.0 and got very similar messages. Here the one from gcc:

main.c: In function ‘f’:
main.c:4:16: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
    4 |     int* ptr = a;
      |                ^
main.c: In function ‘g’:
main.c:10:5: error: invalid operands to binary * (have ‘const int *’ and ‘int *’)
   10 |     *ptr = 1;
      |     ^

I know there is a difference between arrays and pointers, but I always believed there is no difference in function parameter declaration. And isn’t using an array and a pointer as left hand operand in an assignment completely equivalent? After all I also thought that the following were interchangeable:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

int main(int argc, char * argv[])

int main(int argc, char ** argv)

My questions:

  • What is the exact difference between const int * a and const int a[] in a function parameter declaration?

  • Why do I get a warning in one of the cases and an error in the other?

  • Shouldn’t be both cases errors, because I try to change a const parameter?

Edit
as Paul Hankin pointed out I missed a semicolon in the original code. If added, both functions indeed give the same warning message, which is OK, since implicit pointer conversions (like in ptr = a discard const qualifiers.

>Solution :

I get exactly the same messages for both functions in both gcc and clang. You have some typo in the code and didn’t make a copy/paste when you posted it here.

I always believed there is no difference in function parameter declaration.

This is true for plain 1D arrays. An array parameter such as const int a[] will get adjusted ("decay") into a pointer to it’s first element. It is 100% equivalent to const int* a. Note that the const qualifier belongs to the pointed-at type, not the pointer itself.

Now as it happens, incomplete types such as arrays without a size cannot actually be used as function parameters if not for this array adjustment rule1). It’s the very reason why you can even type out an incomplete array type [] without size as a function parameter, because the type gets adjusted before the size of the array matters and the result is not an incomplete type but a pointer (to a complete type).

This equivalence doesn’t scale well to 2D arrays however. An array parameter such as const int a[x][y] is an array of arrays. The first item is of array type const int[y]. So it gets adjusted to a pointer to such a type:
const (*int)[y]. This is not compatible with const int* nor with const int**.


1) C17 6.7.6.3

After adjustment, the parameters in a parameter type list in a function declarator that is part of a definition of that function shall not have incomplete type.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading