Как линкеры разрешают многократно определенные глобальные символы в C - PullRequest
0 голосов
/ 05 ноября 2018

Мой учебник говорит, что:

"Функции и инициализированные глобальные переменные получают сильные символы. Неинициализированные глобальные переменные получают слабые символы. Для сильного символа и нескольких слабых символов выберите сильный символ"

Итак, я создаю два файла, чтобы увидеть:

file1.c:

int number;

int main(int argc, char *argv[]) 
{
    printf("%d",number);
    return 0;
}

file2.c (всего одна строка):

int number = 2018;

и я запустил gcc -Wall -o program file1.c file2.c, и вывод равен 0, что я могу понять, прежде чем изучать компоновщик ('число' в file1.c было инициализировано в 0), но после того, как я изучу, как работает компоновщик, я начинаю удивляться почему вывод не 2018, так как «число» в file2 является сильным символом (инициализированная глобальная переменная), а «число» в file1 является слабым символом, поэтому компоновщик выберет сильное значение со значением 2018, так почему компоновщик выбрать слабый символ?

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

int number; в file1.c не инициализирован. Обратите внимание, что он объявляется в области видимости файла, он объявляется без инициализатора и объявляется без спецификатора класса хранения (в частности, без extern или static). Тогда C 2018 6.9.2 2 говорит:

Объявление идентификатора для объекта, который имеет область файла без инициализатора и без спецификатора класса хранения или со спецификатором класса хранения static, составляет предварительное определение . Если модуль перевода содержит одно или несколько предварительных определений для идентификатора, а модуль перевода не содержит внешнего определения для этого идентификатора, то поведение точно такое, как если бы модуль перевода содержал объявление области файла для этого идентификатора с составным типом как конца блока перевода, с инициализатором, равным 0.

Итак, int number; в file1.c совпадает с int number = 0;. Инициализирован.

Проблема с цитируемым вами текстом заключается в том, что он описывает компоновщик с использованием терминологии для этого компоновщика, и эта терминология отличается от используемой в стандарте C. Стандарт C не имеет никаких «глобальных» переменных, «сильных» или «слабых» символов.

0 голосов
/ 05 ноября 2018

number в file2.c является глобальным, но все еще локально ограничен только этим файлом. Если вы хотите, чтобы file1.c использовал number из file2.c, вам нужно пометить его как extern следующим образом:

extern int number;

int main(int argc, char *argv[]) 
{
    printf("%d",number);
    return 0;
}
...