gcc обрабатывает неинициализированные глобальные переменные, которые явно не объявлены extern
как "общие" символы (отсюда и "COM").
Несколько определений одного и того же общего символа (в нескольких объектных файлах) объединяются компоновщиком при создании конечного исполняемого файла, так что все они ссылаются на одно и то же хранилище. Один из объектных файлов может инициализировать его определенным значением (в этом случае он окажется в разделе данных); если никакие объектные файлы не инициализируют его, он окажется в BSS; если его инициализирует более одного объекта, вы получите ошибку компоновщика.
В итоге, если у вас есть, скажем, два определения int a
:
int a;
в одном объекте и int a;
в другом объекте в порядке: оба ссылаются на один и тот же a
, инициализированный до 0
int a;
в одном объекте и int a = 42;
в другом объекте в порядке: оба ссылаются на один и тот же a
, инициализированный 42
int a = 23;
в одном объекте и int a= 42;
в другом объекте приведут к ошибке ссылки.
Обратите внимание, что использование нескольких определений одного и того же символа в двух объектах технически не разрешено стандартом C; но он поддерживается многими компиляторами, включая gcc, как расширение. (Он указан в разделе «Распространенные расширения» - без каламбура - в спецификации C99.)