2015-10-21 2 views
-6

Рассмотрите следующую программу: (Смотрите демо-версию here).Почему эта программа компилируется в C11, но не в C99?

#include <stdio.h> 
struct Test 
{ 
    int a; 
}; 
typedef struct Test t; 
typedef struct Test t; 
int main() 
{ 
    t T={9}; 
    printf("%d",T.a); 
} 

Программа компилируется в компиляторе C11, но не скомпилирована в компиляторе C99. Зачем? Какова причина? Мой компилятор GCC 4.8.1 дает следующие предупреждения:

[Warning] redefinition of typedef 't' [-Wpedantic] 
[Note] previous declaration of 't' was here 
+1

Компилятор дает вам подсказку или просто отказывается скомпилировать это, не вызывая никаких сообщений об ошибках? – juanchopanza

+5

@PravasiMeet У меня нет, потому что сегодня у меня нет голосов, но, вероятно, потому, что у вас не хватает тщательности и ошибки, которые вы получаете, отсутствуют. – Magisch

+0

@juanchopanza: по умолчанию GCC компилирует это как расширение компилятора, но если я использую параметр -pedantic-errors, то он не скомпилирован? Компилятор дает предупреждения. – Destructor

ответ

8

Это было (видимо) изменилось в С11. C99§6.7/3:

Если идентификатор не имеет связи, не должно быть не более чем одна декларация идентификатора (в описатель или спецификатор типа) с той же области и в том же пространстве имен, за исключением для тегов, указанных в 6.7.2.3.

C11§6.7/3:

Если идентификатор не имеет связей, не должна быть не более чем одна декларации идентификатора (в описателе или спецификаторе типа) с тем же объемом и одно и то же имя, кроме того:

- имя typedef может быть переопределено для обозначения того же типа, что и в настоящее время, при условии, что тип не является измененным типом;

- метки могут быть переоформлены, как указано в 6.7.2.3.

Пока я не могу найти обоснование документа для C11, мое предположение относительно причины этого изменения, чтобы позволить несколько structtypedef с, возможно, в течение нескольких заголовков. Поскольку повторное объявление /enum тегов разрешено уже и typedef ing struct s - довольно распространенная идиома.

Редактировать

@Lundin нашел rationale для этого: он должен повысить совместимость с C++:

C++ позволяет ЬурейеЕ переопределение с тем же именем, что и предыдущей ЬурейиМ появляться

в том же объеме, если он называет тот же тип. Некоторые компиляторы C допускают подобное переопределение типа typedef в качестве расширения, хотя C99 не разрешает его. Добавление добротного переопределения typedef в C1x улучшит согласованность с C++, стандартизирует некоторую существующую практику и безопасно устранит ограничение, которое бесполезно и случайным образом неприятно для пользователей.

+2

Как странно это? Я верю, что вы и его поддержали, но я просто удивляюсь, почему они это сделали? –

+3

@MartinJames это показалось мне и странным. Мое предположение заключалось бы в том, чтобы разрешить несколько «typedef» одной и той же вещи в нескольких заголовках, как и теги. Тем более, что 'typedef struct {...} type;' combos настолько популярны. – Kninnug

+0

У меня есть какая-то неопределенная память о C++, позволяющая несколько typedefs, так что это может быть попытка согласования C с C++? Что касается того, что было бы для него логикой в ​​C++, я понятия не имею. – Lundin

Смежные вопросы