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

Wiki говорит:

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

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

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

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

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

который не должен. AFAIK,

extern int y = 0;  

фактически совпадает с

int i = 0;  

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

Ответ 1

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

ПРИМЕР 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 и инициализатор.

Ответ 2

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

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

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

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

EDIT:

В качестве devnull добавьте комментарии к вопросу OP, Джозеф Майерс из команды gcc объясняет в Сообщить об ошибке:

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