Рассмотрим программу на C, состоящую из двух файлов:
f1.c:
int x;
f2.c:
int x=2;
Мое прочтение параграфа 6.9.2 стандарта C99 состоит в том, что эту программу следует отвергнуть. В моей интерпретации 6.9.2 переменная x
предварительно определена в f1.c
, но это предварительное определение становится фактическим определением в конце единицы перевода и (на мой взгляд) должно вести себя так, как если бы f1.c
содержало определение int x=0;
.
Со всеми компиляторами (и, что немаловажно, компоновщиками) мне удалось попробовать, такого не бывает. Все платформы компиляции, которые я пробовал, связывают эти два файла, и значение x
равно 2 в обоих файлах.
Я сомневаюсь, что это происходит случайно или просто как «легкая» функция, которую можно предоставить в дополнение к тому, что требует стандарт. Если подумать, это означает, что в компоновщике есть специальная поддержка тех глобальных переменных, у которых нет инициализатора, в отличие от тех, которые явно инициализированы нулем. Кто-то сказал мне, что компоновщик все равно может понадобиться для компиляции Фортрана. Это было бы разумным объяснением.
Есть мысли по этому поводу? Другие интерпретации стандарта? Названия платформ, на которых файлы f1.c
и f2.c
отказываются связываться между собой?
Примечание: это важно, потому что вопрос возникает в контексте статического анализа. Если два файла могут отказаться линковаться на какой-то платформе, анализатор должен пожаловаться, но если каждая платформа компиляции это принимает, то нет причин предупреждать об этом.
a[10] = 0;
, даже еслиa
являетсяint a[1];
, что также было и разрешено как общее расширение (до того, как у нас появились гибкие элементы массива). Я думаю, следует четко отметить, что это формально неопределенное поведение, в дополнение к определенному поведению на некоторых платформах. 29.09.2009extern
делает его объявлением, а не определением, поэтому невозможно иметь несколько определений с явным ключевым словомextern
. 01.06.2012