1

I am trying to call a c function with a const matrix argument using a const cast, but can't find the syntax that stops the gcc compiler complaining. The code below compiles without complaining if all "const " casts are removed. The quesion is similar to C function const multidimensional-array argument strange warning but no fully satisfactory solution was offered there. In the following code, if the first call to g() works, then the second call to g() should also work, since it is syntactically identical. But it does not. The second version of g() is preferred, because it does not require knowing in advance the type of the matrix.

/* file t.c */
void f(const int a[2]) {/*empty*/}
void g(const int b[2][2]) {/*empty*/}

int main()
{
    int a[2];
    int b[2][2];

    f((const int (*)) a);                   /* ok */
    f((const typeof(&a[0])) a);             /* ok */
    g((const int (*)[2]) b);                /* ok */
    g((const typeof(&b[0])) b);             /* compiler complains */
}

$ gcc -o t t.c
t.c: In function ‘main’:
t.c:13:2: warning: passing argument 1 of ‘g’ from incompatible pointer type [enabled by default]
  g((const typeof(&b[0])) b);  /* compiler complains */
  ^
t.c:3:10: note: expected ‘const int (*)[2]’ but argument is of type ‘int (*)[2]’
     void g(const int b[2][2]) {/*empty*/}
Community
  • 1
  • 1
ajsh
  • 11
  • 1
  • 1
    `const typeof(&b[0])` is `int (* const)[2]`, not `const int (*)[2]`, i.e. the pointer itself is const, not the elements. – Tavian Barnes Jul 11 '15 at 23:02
  • 1
    The cast doesn't do anything useful. You can just call the functions as `f(a)` and `g(b)`. – user3386109 Jul 11 '15 at 23:23
  • Yes, one can just call the functions as f(a) and g(b), and everything works. The problem is simply the compiler complaining. I have a large code that calls library functions with const arguments. gcc litters the compilation with complaints that should not be there. – ajsh Jul 12 '15 at 14:55

2 Answers2

2

Yes, this lack of possibility to call a function with const 2D arrays with a non-const argument is really a defect in the C specification.

To move around it remember that

void g(const int b[2][2]) {/*empty*/}

is rewritten as

void g(const int (*b)[2]) {/*empty*/}

so this shows you how you'd have to convert, to a const int (*)[2], that is a pointer to an array of 2 double.

g( (const int (*)[2])b );
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • The gcc error message is also helpful in remembering how to write the type: `expected 'const int (*)[2]' but argument is of type 'int (*)[2]'` – rici Jul 12 '15 at 02:42
  • This is all correct. The issue is that int (*)[2])b should be the same as typeof(&b[0]) (I think), but the compiler does not recognize them as the same. – ajsh Jul 12 '15 at 14:59
  • @ajsh, no it should be the same as `typeof(&b)` without the `[0]`. – Jens Gustedt Jul 12 '15 at 16:05
-1

The const in the declaration header means that the function cannot change the contents of the argument. It is an information to the caller(compiler) and programmer. So there is no reason to make a const typecast then calling the function. It is totally superfluous.

Alex Celeste
  • 12,824
  • 10
  • 46
  • 89