Два только частично эквивалентны. Разница в том, что:
static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
объявляет двумерный массив, который включает выделение пространства для массива и обеспечение того, чтобы daytab
ссылался на эту память. Тем не менее:
static char (*daytab)[13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
... объявляет только указатель. Итак, вы пытаетесь инициализировать указатель с помощью инициализатора массива, который работает не так, как ожидалось. Там нет массива; нет памяти, выделенной для массива. Вместо этого происходит то, что первое число в вашем инициализаторе присваивается указателю daytab
, и компилятор генерирует предупреждение, чтобы вы знали, что вы указали много дополнительных значений, которые просто отбрасываются. Поскольку первое число в вашем инициализаторе - 0
, вы просто устанавливаете daytab
в NULL
довольно многословно.
Так что, если вы хотите выполнить инициализацию такого рода, используйте первую версию - она распадается на тот же тип указателя, который вы явно объявили во второй версии, так что вы можете использовать его таким же образом. Вторая версия с указателем массива необходима, если вы хотите динамически выделить массив или получить ссылку на другой массив, который уже существует.
Так что вы можете сделать это:
static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;
ptr = arr;
... и затем используйте ptr
и arr
взаимозаменяемо. Или это:
static char (*ptr)[3] = NULL;
ptr = malloc(2 * sizeof(*ptr));
... чтобы получить динамически размещаемый двумерный массив (не массив указателей на одномерные массивы, а реальный двумерный массив). Конечно, в этом случае он не инициализируется.
«Эквивалентность» этих двух вариантов просто означает, что 2D-массив, когда он распадается на указатель на свой первый элемент, распадается на тип указателя, объявленный во втором варианте. Как только версия указателя фактически указана на массив, они эквивалентны. Но версия 2D-массива устанавливает память для массива, где объявление указателя не ... и указателю может быть присвоено новое значение (указывающее на другой массив), где переменная 2D-массива не может.
В C99 вы можете сделать это, хотя (если не static
по крайней мере):
char (*daytab)[13] = (char [][13]){
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};