0

While the following code behaves as expected on Godbolt, I'm wondering if, from a standard perspective, casting int [n][m] -> int [n*m] was allowed.

#define ROW 2
#define COL 10

void test(int arr[ROW * COL]) {
    for (int i = 0; i < (ROW * COL); i++) {
        printf("%d\n", arr[i]);
    }
}

int main() {

    // build an array
    int arr[ROW][COL];
    for (int i = 0; i < ROW; i++) {
        for (int j = 0; j < COL; j++) {
            arr[i][j] = i * 10 + j;
        }
    }

    // Make the conversion
    int* converted = (int*)arr; //< The conversion
    test(converted);
    return 0;
}

If you want to try it: godbolt

gberth
  • 467
  • 5
  • 13
  • Yes. Arrays are defined as consecutive elements, so your array of arrays is consecutive ints. – stark May 08 '23 at 14:39
  • 1
    @stark: The fact the underlying memory layout is defined to be the same does not mean the C rules for types, aliasing, and pointer arithmetic support it. – Eric Postpischil May 08 '23 at 14:42
  • The cast isn’t int [n][m] -> int [n\*m], it’s actually int (*)[10] -> int *. Both are simply pointers to int, perfectly legal. – Paul Lynch May 08 '23 at 14:53
  • 1
    @PaulLynch: `int (*)[10]` is not a pointer to `int`. – Eric Postpischil May 08 '23 at 15:00
  • @EricPostpischil You are correct that this is UB since the pointer arithmetic isn't specified to work out of bounds. But as far as aliasing goes, it is quite clear (6.5): "An object shall have its stored value accessed only by an lvalue expression that has one of the following types:" /--/ "- an aggregate or union type that includes one of the aforementioned types among its members". `b[i]` is a lvalue expression of type `int` and so the compiler cannot assume that it does not change `a` since it's an aggregate with `int` among its members. – Lundin May 09 '23 at 11:55

0 Answers0