Pass a two dimensional array to a function of constant parameter
I learned from C Primer Plus that if you want to protect an array from being accidentally modified by a function, you should add const
modifier before the pointer declaration in the header of function definition.
Following this sensible advice, in the following minimal example, I'm trying to pass a non-constant two-dimensional array array
to the function Sum2D
, one parameter of which is a pointer-to-const-int[2]
.
#include <stdio.h>
#define ROWS 2
#define COLS 2
int Sum2D(const int ar[][COLS], int rows); //use `const` to protect input array
int main(void)
{
int array[ROWS][COLS]={{1,2},{3,4}}; //the non-constant array
printf( "%d\n", Sum2D(array,ROWS) );
return 0;
}
int Sum2D(const int ar[][COLS], int rows)
{
int total=0;
int i,j;
for( i=0 ; i<rows ; i++ )
{
for( j=0 ; j<COLS ; j++ )
{
total+=ar[i][j];
}
}
return total;
}
However, gcc
cannot successfully compile this code without issuing the following warnings:
$gcc -ggdb3 -Wall -Wextra -o test test.c
test.c: In function ‘main’:
test.c:16:2: warning: passing argument 1 of ‘Sum2D’ from incompatible pointer type [enabled by default]
printf( "%d\n", Sum2D(array,4) );
^
test.c:4:5: note: expected ‘const int (*)[4]’ but argument is of type ‘int (*)[4]’
int Sum2D(const int ar[][COLS], int rows);
^
1) Why the warning?
2) How can I eliminate the "noise"?(Apart from adding const
to array
declaration.)
(If the array
and function both use one-dimensional array, there is no warning.)
System information:
Ubuntu 14.04LTS
Compiler: gcc 4.8.2
This is an unfortunate "bug" in C's design; T (*p)[N]
does not implicitly convert to T const (*p)[N]
. You will have to either use an ugly cast, or have the function parameter not accept const
.
At first sight it looks like this conversion should be legal. C11 6.3.2.3/2:
For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type;
However also look at C11 6.7.3/9 (was /8 in C99):
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
This last quote says that int const[4]
is not considered to be a const
-qualified version of int[4]
. Actually it is a non-const
-qualified array of 4 const int
s. int[4]
and int const[4]
are arrays of different element types.
So 6.3.2.3/2 does not in fact permit int (*)[4]
to be converted to int const (*)[4]
.
Another weird situation where this issue with const
and arrays shows up is when typedefs are in use; for example:
typedef int X[5];
void func1( X const x );
void func1( int const x[5] );
This would cause a compiler error: X const x
means that x
is const, but it is pointing to an array of non-const int
s; whereas int const x[5]
means x
is not const but it is pointing to an array of const ints!
Further reading here, thanks to @JensGustedt