Оба действительны в C , но не в C ++ . Вы бы обычно были бы правы:
char *x[]; // array of pointers to char
char (*y)[]; // pointer to array of char
Однако массивы распадаются на указатели, если они появляются в качестве параметров функции. Так они становятся:
char **x; // Changes to pointer to array of pointer to char
char (*y)[]; // No decay, since it's NOT an array, it's a pointer to an array
В типе массива в C допускается не указывать один из размеров. Это, должно быть, самый левый (к сожалению, сначала я сказал самый правый). Таким образом,
int valid_array[][5]; // Ok
int invalid_array[5][]; // Wrong
(Вы можете связать их ... но у нас редко есть причина для этого ...)
int (*convoluted_array[][5])[][10];
Существует ловушка, , и ловушка в том, что тип массива с []
является неполным типом. Вы можете передать указатель на неполный тип, но некоторые операции не будут работать, так как им нужен полный тип. Например, это не будет работать:
void func(int (*x)[])
{
x[2][5] = 900; // Error
}
Это ошибка, потому что для того, чтобы найти адрес x[2]
, компилятор должен знать, насколько велики x[0]
и x[1]
. Но x[0]
и x[1]
имеют тип int []
- неполный тип без информации о его размере. Это станет более понятным, если вы представите, какой будет «не затухшая» версия типа, которая является int x[][]
- очевидно, недействительной C. Если вы хотите передать двумерный массив в C, у вас есть несколько вариантов :
Передать одномерный массив с параметром размера.
void func(int n, int x[])
{
x[2*n + 5] = 900;
}
Использовать массив указателей на строки. Это немного неуклюже, если у вас есть подлинные 2D-данные.
void func(int *x[])
{
x[2][5] = 900;
}
Используйте фиксированный размер.
void func(int x[][5])
{
x[2][5] = 900;
}
Использовать массив переменной длины (только C99, поэтому он, вероятно, не работает с компиляторами Microsoft).
// There's some funny syntax if you want 'x' before 'width'
void func(int n, int x[][n])
{
x[2][5] = 900;
}
Это частая проблемная область даже для ветеранов Си. Во многих языках отсутствует встроенная поддержка "из коробки" для реальных, многомерных массивов переменного размера (C ++, Java, Python), хотя у некоторых языков она есть (Common Lisp, Haskell, Fortran). Вы увидите много кода, который использует массивы массивов или вычисляет смещения массива вручную.