Почему компиляторы C добавляют подчеркивания к внешним именам? - PullRequest
33 голосов
/ 13 апреля 2010

Я работаю в C так долго, что тот факт, что компиляторы обычно добавляют подчеркивание к началу extern, только что понятен ... Однако еще один SO вопрос сегодня получил меня задаваясь вопросом об истинной причине, почему подчеркивание добавлено. статья в Википедии утверждает, что причина:

Обычной практикой для компиляторов C было добавление начальных подчеркиваний ко всем идентификаторам программ внешней области видимости для предотвращения столкновений с помощью поддержки языка времени выполнения

Я думаю, что по крайней мере в этом есть доля правды, но, похоже, на самом деле нет ответа на этот вопрос, поскольку добавление подчеркивания ко всем внешним элементам не сильно поможет в предотвращении столкновений.

Есть ли у кого-нибудь хорошая информация об обосновании основного подчеркивания?

Является ли добавленное подчеркивание одной из причин того, что системный вызов Unix creat() не заканчивается на 'e'? Я слышал, что ранние компоновщики на некоторых платформах имели ограничение в 6 символов для имен. Если это так, то добавление подчеркивания к внешним именам может показаться совершенно безумной идеей (теперь у меня есть только 5 символов для игры ...).

Ответы [ 5 ]

17 голосов
/ 13 апреля 2010

Обычной практикой для компиляторов C было добавление начальных подчеркиваний ко всем идентификаторам программ внешней области видимости для предотвращения столкновений с использованием поддержки языка времени выполнения

Если бы поддержка во время выполнения была предоставлена ​​компилятором, вы могли бы подумать, что вместо этого стоит добавить подчеркивание к нескольким внешним идентификаторам в поддержке времени выполнения!

Когда впервые появились компиляторы C, основной альтернативой программированию на C на этих платформах было программирование на языке ассемблера, и было (и иногда до сих пор) полезно связывать вместе объектные файлы, написанные на ассемблере и C. Так что действительно (IMHO) ) главное подчеркивание, добавленное к внешним идентификаторам C, состояло в том, чтобы избежать конфликтов с идентификаторами в вашем коде сборки.

(См. Также Расширение метки asm в GCC ; и обратите внимание, что это добавленное подчеркивание можно считать простой формой искажения имени . Более сложные языки, такие как C ++, используют более сложные имена покалечившись, но это то, с чего все началось.)

5 голосов
/ 13 апреля 2010

, если компилятор c всегда ставит подчеркивание перед каждым символом, тогда код запуска / c-runtime (который обычно пишется на ассемблере) может безопасно использовать метки и символы, которые не начинаются с подчеркивания (например, символ «start»).

, даже если вы пишете функцию start () в коде c, она генерируется как _start в выходных данных объекта / asm. (обратите внимание, что в этом случае код c не может сгенерировать символ, который не начинается с подчеркивания), поэтому стартовому кодировщику не нужно беспокоиться о изобретении непонятных невероятных символов (таких как $ _dontuse42% $) для каждого из его / ее глобальные переменные / метки.

так что компоновщик не будет жаловаться на конфликт имен, и программист счастлив. :)

следующее отличается от практики компилятора, добавляющего подчеркивание в свои выходные форматы.

Эта практика была позже кодифицирована как часть стандартов языка C и C ++, в которых использование ведущих подчеркиваний было зарезервировано для реализации.

Это соглашение соблюдается для библиотек c sytem и других системных компонентов. (и для таких вещей, как __FILE__ и т. д.).

(обратите внимание, что такой символ (например, _time) может привести к 2 ведущим подчеркиваниям (__time) в сгенерированном выводе)

3 голосов
/ 13 апреля 2010

Основная функция не является реальной точкой входа исполняемого файла. Некоторые статически связанные файлы имеют реальную точку входа, которая в конечном итоге вызывает main, и эти статически связанные файлы имеют пространство имен, которое не начинается с подчеркивания. В моей системе в / usr / lib есть gcrt1.o, crt1.o и dylib1.o. У каждого из них есть функция «start» без подчеркивания, которая в конечном итоге вызовет точку входа «_main». Все остальное, кроме этих файлов, имеет внешнюю область видимости. История имеет отношение к смешиванию ассемблера и C в проекте, где все C считались внешними.

3 голосов
/ 13 апреля 2010

Из того, что я всегда слышу, следует избегать конфликтов имен. Не для других внешних переменных, а для того, чтобы при использовании библиотеки она не конфликтовала с именами переменных пользовательского кода.

2 голосов
/ 13 апреля 2010

Из Википедия :

Для компиляторов C было обычной практикой ставить перед всеми внешними идентификаторами программы области видимости подчеркивание, чтобы предотвратить конфликты с вкладами из языковой поддержки времени выполнения. Кроме того, когда компилятору C / C ++ необходимо было вводить имена во внешнюю связь как часть процесса перевода, эти имена часто отличались некоторой комбинацией нескольких начальных или конечных подчеркиваний.

Впоследствии эта практика была кодифицирована как часть стандартов языка C и C ++, в которых использование ведущих подчеркиваний было зарезервировано для реализации.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...