Почему компиляторы C предварительно ожидают символы нижнего подчеркивания к внешним именам?

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

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

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

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

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

34
задан Community 23 May 2017 в 12:02
поделиться

5 ответов

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

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

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

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

18
ответ дан 27 November 2019 в 17:13
поделиться

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

3
ответ дан 27 November 2019 в 17:13
поделиться

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

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

Эта практика была позже кодифицирована. как часть стандартов языков C и C ++, в которых использование начальных подчеркиваний было зарезервировано для реализации.
2
ответ дан 27 November 2019 в 17:13
поделиться

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

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

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

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

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

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

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

5
ответ дан 27 November 2019 в 17:13
поделиться

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

3
ответ дан 27 November 2019 в 17:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: