passing in int* for int[][] C/C++

Viewed 133

Suppose I have the following code

#include <stdio.h>
#include <stdlib.h>

int foo(int bar[3][3]){
    return bar[1][1];
}

int main(){
    int* bar = (int*) malloc(9 * sizeof(int));
    for(int i = 0; i < 9; i++){
        bar[i] = i;
    }
    int test = foo(bar);
    printf("%d\n", test);
}

Compiling this with C gives a warning

warning: incompatible pointer types passing 'int *' to parameter of type 'int (*)[3]' [-Wincompatible-pointer-types]
    int test = foo(bar);

But still outputs the expected result of 4 (Although I imagine the warning is a sign of UB)

Compiling with g++ gives an error

error: no matching function for call to 'foo'
    int test = foo(bar);
note: candidate function not viable: no known conversion from 'int *' to 'int (*)[3]' for 1st argument
int foo(int bar[3][3]){

I cannot change the function signature of bar but would like to just pass in a simple pointer to the array. What is the simplest typecast/change of code that would make this compile with no UB with g++. This is for code that I am generating with a Python script while looking at the function signature of bar so the simpler the solution the better. (This is just an example)

3 Answers

Quick and dirty fix:

foo(reinterpret_cast<int(*)[3]>(bar)); // C++ only
foo((int(*)[3])bar); // C and C++

Replaces the implicit cast present in C language with an explicit one to let the C++ compiler know you are intending to circumvent the type-system.

Without dynamic memory allocation:

int main(void) {
   int bar[3][3];
   for (int i=0; i<9; ++i) {
      bar[i / 3][i % 3] = i;
   }

   printf("%d\n", foo(bar));
}

With: (C)

int main(void) {
   int (*bar)[3] = malloc(3 * sizeof(int[3]));

   for (int i=0; i<9; ++i) {
      bar[i / 3][i % 3] = i;
   }

   printf("%d\n", foo(bar));
}

What is the simplest typecast/change of code that would make this compile with no UB with g++

int main(){
    int bar[3][3];
    for(int i = 0; i < 9; i++){
        bar[i / 3][i % 3] = i;
    }
    int test = foo(bar);
    printf("%d\n", test);
}

Works in both C++ and C

Related