Так зачем вообще использовать int (* a) [3], если в конце концов мне придется использовать malloc?
Это очень полезно для массивов переменной длины, когда вы хотите создать массив real 2d с использованием динамической памяти:
#include <stdio.h>
#include <stdlib.h>
void *fn_alloc(int rows, int cols)
{
int (*arr)[cols];
int i, j;
arr = malloc(sizeof(int [rows][cols]));
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
arr[i][j] = (i * cols) + j;
}
}
return arr;
}
void fn_print(int rows, int cols, int (*arr)[cols])
{
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
printf("\t%d", arr[i][j]);
}
printf("\n");
}
}
int main(void)
{
int rows, cols;
scanf("%d %d", &rows, &cols);
int (*arr)[cols] = fn_alloc(rows, cols);
fn_print(rows, cols, arr);
free(arr);
return 0;
}
Другими словами, когда задействована динамическая память, ваше первое объявление полезно для указания на массив из n измерений , а второе полезно для указания на массив массива из n размеры .