Ответ 1
Я думаю, что то, что вы ищете, - это глава §6.2.7 из стандарта C11
, тип совместимого и составного типа (выделение мое)
Все объявления, относящиеся к одному и тому же объекту или функции, должны иметь совместимый тип; в противном случае поведение undefined.
и связанных с совместимым типом,
Два типа имеют совместимый тип, если их типы одинаковы.
В вашем случае int
и unsigned int
не являются совместимыми типами. Следовательно, undefined поведение.
Чтобы добавить немного ясности, в вашем источнике 2 unsigned int var_global;
- это объявление, и оно не соответствует другому объявлению (и определению), поэтому это UB.
Тем не менее, утверждение вроде
printf("%d \n",var_global);
всегда будет считать аргумент %d
типом int
. Если тип и спецификатор формата не совпадают, вы снова вызываете undefined поведение.
EDIT:
После редактирования ответ получится, используйте -fno-common
, чтобы получить желаемую ошибку. (пропустил extern
, с чем вас беспокоит, я считаю).
Цитата из онлайн-справочника GCC,
-fno-common
В коде C управляет размещением неинициализированных глобальных переменных. Компиляторы Unix C традиционно допускали множественные определения таких переменных в разных единицах компиляции, помещая переменные в общий блок. Это поведение, заданное как -fcommon, и является значением по умолчанию для GCC для большинства целей.. С другой стороны, это поведение не требуется по ISO C, а на некоторых объектах может нести ограничение скорости или размера кода на переменные ссылки. Параметр -fno-common указывает, что компилятор должен размещать неинициализированные глобальные переменные в разделе данных объектного файла, а не генерировать их как общие блоки. Это означает, что если одна и та же переменная объявлена (без
extern
) в двух разных компиляциях, вы получаете ошибку с множественным определением при связывании. В этом случае вы должны скомпилировать с помощью - Вместо этого. Компиляция с -fno-common полезна для целей, для которых она обеспечивает лучшую производительность, или если вы хотите убедиться, что программа будет работать в других системах, которые всегда обрабатывают неинициализированные объявления переменных таким образом.
Я не знаю ни одного упоминания о формулировках "одного правила определения" в стандарте C, но по линии вы можете посмотреть приложение "J.5.11", "Несколько внешних определений",
Может быть более одного внешнего определения для идентификатора объекта, с или без явного использования ключевого слова
extern
; если определения не совпадают или больше, чем один инициализирован, поведение undefined.