Рассмотрим параллели между:
typedef struct C { int i; };
extern struct P { int i; };
GCC 4.2.1 без явных предупреждений (gcc -c xxx.c
) говорит о первом:
xxx.c:1: warning: useless storage class specifier in empty declaration
xxx.c:2: warning: useless storage class specifier in empty declaration
Обратите внимание, что они толькопредупреждения;они не являются ошибкой, потому что стандарт допускает обозначения, хотя он не делает очень много.В каждом случае в примере просто объявляется тип структуры, который может использоваться именем struct C
или struct P
.Классы хранения не имеют значения, потому что ни один объект не назван.В C ++ эти объявления также объявляют типы C
и P
(но это также может произойти, если typedef
или extern was not there); in C, those types (
C and
P`) не объявлены.
ВВ стандарте C typedef
рассматривается как класс хранения, как extern
и static
- классы хранения.Это означает, что следующий код является допустимым:
typedef struct C { int i; } name1;
extern struct P { int i; } name2;
Он объявляет те же два типа структуры, что и раньше, но теперь typedef
объявляет псевдоним для struct C
, который равен name1
, и *В строке 1026 * указано, что другая единица перевода (TU) определяет переменную с именем name2
типа struct P
.Ни один из них не является пустым (за исключением того, что определения не используются позже в показанном двухстрочном TU).
Стандарт C допускает много странных вещей.Например:
int unsigned typedef u;
Это совершенно правильный, но совершенно ненормальный способ написания:
typedef unsigned int u;
В C99 есть раздел §6.11.5 (в разделе «Будущие языковые инструкции»)которая гласит:
6.11.5 Спецификаторы класса хранения
Размещение спецификатора класса хранения, отличного от начала описателей объявления в объявлении, является устаревшей функцией.
Это делает мой странный пример с нарушением §6.11.5.
Резюме
- Рассмотренный код синтаксически корректен в C, как C89, так иC99.
- Кроме того, AFAIK синтаксически допустим в C ++ - но это даже более бессмысленно, чем в C, поскольку
struct C { int i; };
без typedef вводит тип C (а также struct C
). - Рассмотренный код не должен приниматься - разумно требовать его исправления.
Правильным исправлением может быть удаление класса хранения (typedef
) или егоможет быть, ввести имя в качестве псевдонима для struct C
,Поскольку код компилируется без псевдонима, правильнее удалить класс хранилища.