#c
#c
Вопрос:
В соответствии с приведенным ниже кодом и ответом на него:
Вопрос: Какое из следующих объявлений структуры выдаст ошибку?
struct temp { char c; } s; int main(void) {}
struct temp { char c; }; struct temp s; int main(void) {}
struct temp s; struct temp { char c; }; int main(void) {}
Ничего из вышеперечисленного.
Ответ: 4
Это правильно? Можем ли мы сначала объявить объект структуры и только потом определение структуры?
Комментарии:
1. Все показанные функции являются нестандартными для всего текущего тысячелетия. Все структуры искажены. Ни один код не должен компилироваться.
2. Предполагается, что вы не сможете скомпилировать пустое тело структуры. В (c) нет типа
struct temp
,s
который номинально определен, поэтому переменная не должна быть определяемой. Где-то может быть карта, освобождающая от тюрьмы; У меня нет компилятора C на моем iPhone.3. @JonathanLeffler Вопрос касается порядка объявлений, элементы структуры не имеют значения. Я добавил
int main
и элемент структуры, и он по-прежнему компилируется без предупреждений. Я также добавил телоmain
, которое обращается к элементу структуры, никаких жалоб. Я так же удивлен, как и OP.4. Я сплю. Теперь мой робот отвечает. Если утром все еще будут разногласия, я посмотрю. Если вам когда-нибудь нужны были доказательства того, почему вопросы с несколькими вариантами ответов отвратительны, это иллюстрирует суть. Вы не можете представить рассуждения на экзамене.
5. @jonathan: Пустые структуры являются расширением GCC для C.
Ответ №1:
Да, C иногда бывает странным. Поскольку эта переменная находится в области видимости файла и не имеет инициализатора или спецификатора класса хранения, она представляет собой предварительное определение. Стандарт C определяет его следующим образом:
6.9.2 Определения внешних объектов
Объявление идентификатора для объекта, имеющего область видимости файла, без инициализатора и без спецификатора класса хранения или со статическим спецификатором класса хранения, представляет собой предварительное определение. Если модуль трансляции содержит одно или несколько предварительных определений для идентификатора, а модуль трансляции не содержит внешнего определения для этого идентификатора, то поведение будет точно таким же, как если бы модуль трансляции содержал объявление области видимости файла этого идентификатора с составным типом на конец блока трансляции, синициализатор равен 0.
Я подчеркнул соответствующую часть. Поскольку в вашей переменной нет инициализатора, это как если бы вы записали его в самом конце файла и инициализировали нулем. Физический макет файла не имеет значения, потому что логически определение типа структуры доступно в конце файла.
Итак, ответ действительно (4). Я бы не стал писать подобный код в реальной жизни, однако это ужасно сбивает с толку в экосистеме C, где почти все должно быть предварительно объявлено для использования.