Ответ 1
Эти два лишь частично эквивалентны. Разница заключается в том, что:
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));
... получить динамически распределенный 2-мерный массив (не массив указателей на 1D-массивы, а реальный 2D-массив). Конечно, в этом случае он не инициализируется.
"Эквивалентность" двух вариаций просто означает, что 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}
};