Как определить переменную extern вместе с объявлением?


Wiki говорит:

Ключевое слово extern означает "объявить без определения". Другими словами, это способ явного объявления переменной или принудительного объявления без определения. также можно явно определить переменную, то есть принудительно задать определение. Это делается путем присвоения переменной значения инициализации .

Это означает, что объявление extern, которое инициализирует переменную, служит определением для этого переменная . Итак,

/* Just for testing purpose only */ 
#include <stdio.h>
extern int y = 0;
int main(){
    printf("%dn", y);
    return 0;
}

Должно быть допустимым (скомпилировано в C++11 ). Но при компиляции с опциями -Wall -Wextra -pedantic -std=c99 в GCC 4.7.2, выдает предупреждение:

[Warning] 'y' initialized and declared 'extern' [enabled by default]

Чего не должно быть. АФАИК,

extern int y = 0;  

Фактически то же самое, что

int i = 0;  

Что здесь не так ?

2 12

2 ответа:

Все три версии стандарта-ISO / IEC 9899: 1990, ISO/IEC 9899: 1999 и ISO/IEC 9899: 2011-содержат пример в разделе с названием определения внешних объектов (§6.7.2 C90 и §6.9.2 C99 и C11), который показывает:{[6]]}

Пример 1

int i1 = 1;        // definition, external linkage
static int i2 = 2; // definition, internal linkage
extern int i3 = 3; // definition, external linkage
int i4;            // tentative definition, external linkage
static int i5;     // tentative definition, internal linkage
Пример продолжается, но строка extern int i3 = 3; ясно показывает, что стандарт указывает, что это должно быть разрешено. Заметьте, однако, что примеры в стандарте технически не являются "нормативными" (см. предисловие в стандарте); они не являются окончательным утверждением того, что разрешено, а что нет. Тем не менее, большинство людей большую часть времени не используют extern и инициализатор.

Этот код абсолютно корректен.

Но любой компилятор волен выдавать дополнительную (информативную или нет) диагностику:

(C99, 5.1.1. 3p1 fn 8) " конечно, реализация свободна производить любое количество диагностик, пока действительная программа все еще правильно переведена."

Чего компилятор не может сделать, так это не выдавать диагностику, когда есть ограничение или нарушение синтаксиса.

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

Как девнулл вставил в ОП комментарий к вопросу, Джозеф Майерс из команды gcc объясняет в отчете об ошибке , подвергающем сомнению эту диагностику:

" это предупреждение стиля кодирования-код действителен, но чрезвычайно unidiomatic для C, поскольку "extern" обычно означает, что объявление не дает определения объекта."