Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

Семантика объявлений 2D-массивов в Си

#c


Не могу понять семантику следующего выражение на Си:

char (*daytab)[13]


Оно эквивалентно такому выражению:

char daytab[2][13]


В первом выражении сообщается, что так объявленный параметр функции - указатель на
массив из 13 элементов. Наличие круглых скобок здесь обязательно, потому что квадратные
скобки [] имеют больший приоритет, чем знак ссылки *. Без скобок это было бы объявление
массива из 13 указателей на данные типа char:

char daytab[13]


Объясните, что происходит в первом определении? Подобные конструкции под капотом,
как правило, выглядят очень просто: как работа с каким-нибудь регистром EDI, а понять
семантику таких выражений бывает нелегко.

Если разбирать первый пример по частям справа налево, то можно попытаться объяснить
это так:


объявляется массив из 13 элементов
Слева находится тип данных, хранящихся в массиве
типа данных char (*daytab) не поддается человеческой интерпретации, и здесь я застопорился


Помогите разобраться
    


Ответы

Ответ 1



В с/с++ не разбирают справа-налево. А разбирают по спирали. Вот есть чудесный сервис - http://www.cdecl.org/ , который помогает парсить подобые вещи.

Ответ 2



Если быть точнее, оно эквивалентно такому выражению: char daytab[ ][13]. А начинать надо со скобок, а не справа: указатель на массив из 13 элементов типа char. В общем-то KoVadim все нужное и так написал.

Ответ 3



Поскольку формально все уже рассказали, рискну немного развлечь... // попробуем исследовать эту загадку с помощью gcc компилятора #include #include #include #include // начнем строить предположения, отталкиваясь от уже имеющихся знаний // и проверять их, пытаясь скомпилировать код, который будем потихоньку писать int main (int ac, char *av[]) { // хотя бы скомпилиться? char (*dtime)[26]; // OK я взял 26 с целью использовать далее ctime() // пойдем последовательно // судя по звездочке в скобках dtime похоже указатель, // а [] говорят, что он указывает на массив, очевидно из char-ов // проверим... printf("sizeof(d) : %ld sizeof(*d) : %ld\n", sizeof(dtime), sizeof(*dtime)); // ага, сама переменная занимет 8 байт на X86-64, // это подтверждает предположение, что это указатель // и указывает он на область памяти размером 26 * sizeof(char) // при таком раскладе память под массив никто за нас не выделит dtime = (typeof(dtime))malloc(sizeof(*dtime)); // а приводим тип для g++ (вдруг кто-то его очень любит) // (бредовый компайлер, не верит, что void * такой же адрес, как и цель) // теперь посмотрим как можно обращаться с переменной этого "типа" time_t t = time(0); // память на которую указывает dtime ведет себя как nil-terminated string? ctime_r(&t, dtime[0]); puts(strlen(*dtime) < 26 ? "размерчик угадали" : "оппа... портим память"); // распечатаем посимвольно int i; for (i = 0; i < sizeof(*dtime); i++) putchar((*dtime)[i]); free(dtime); // valgrind утверждает, что с heap все OK return puts("End") == EOF; // и закончим, вернув 0 (я надеюсь, что терминал не сломан) } @typemoon, и где Вы такие штучки находите?

Комментариев нет:

Отправить комментарий