вопросы об искажении имени в C++

Я пытаюсь изучить и понять искажение имени в C++. Вот некоторые вопросы:

(1) От devx

Когда глобальная функция перегружается, сгенерированное скорректированное имя для каждой перегруженной версии уникально. Искажение имени также применяется к переменным. Таким образом локальная переменная и глобальная переменная с тем же пользовательским именем все еще получают отличные скорректированные имена.

Есть ли другие примеры, которые используют искажение имени помимо перегрузки функций и того-же-имени глобальные и локальные переменные?

(2) От Wiki

Потребность возникает, где язык позволяет различным объектам быть названными с тем же идентификатором, пока они занимают другое пространство имен (где пространство имен обычно определяется модулем, классом или явной директивой пространства имен).

Я не вполне понимаю, почему искажение имени только применяется к случаям, когда идентификаторы принадлежат различным пространствам имен, начиная с перегрузки функций может быть в том же пространстве имен и том-же-имени, которым глобальные и локальные переменные могут также быть в том же пространстве. Как понять это?

Переменные с тем же именем, но в различных объемах также используют искажение имени?

(3) C имеет искажение имени? Если это не делает, как это может иметь дело со случаем, когда некоторые глобальные и локальные переменные имеют то же имя? C не имеет перегружающихся функций, правильно?

Спасибо и всего наилучшего!

23
задан Igor Kustov 6 January 2017 в 14:34
поделиться

4 ответа

C не изменяет имена, но добавляет подчеркивание к именам функций, поэтому printf (3) на самом деле является _printf в объекте libc.

В C ++ дело обстоит иначе. История этого состоит в том, что изначально Страуструп создал "C с классами" или cfront , компилятор, который переводил ранний C ++ на C. Затем остальные инструменты - компилятор C и компоновщик, которые мы использовали бы для создания объектного кода. . Это означало, что имена C ++ нужно было каким-то образом переводить в имена C. Это именно то, что делает изменение имени . Он предоставляет уникальное имя для каждого члена класса, а также функции и переменной глобального / пространства имен, поэтому имена пространств имен и классов (для разрешения) и типы аргументов (для перегрузки) каким-то образом включены в окончательные имена компоновщика.

Это очень легко увидеть с помощью таких инструментов, как nm (1) - скомпилируйте исходный код C ++ и посмотрите на сгенерированные символы. Следующее находится в OSX с GCC:

namespace zoom
{
    void boom( const std::string& s )
    {
        throw std::runtime_error( s );
    }
}

~$ nm a.out | grep boom
0000000100001873 T __ZN4zoom4boomERKSs

И в C, и в C ++ локальные (автоматические) переменные не производят символов, но находятся в регистрах или в стеке.

Редактировать:

Локальные переменные не имеют имен в результирующем объектном файле по той простой причине, что компоновщику не нужно о них знать. Так что без имени, без искажений. Все остальное (на что компоновщик должен обратить внимание) в C ++ искажено по именам.

27
ответ дан 29 November 2019 в 01:10
поделиться

Существуют ли другие примеры, использующие изменение имен, помимо функций перегрузки и одноименных глобальных и локальных переменных?

C ++ всегда искажает все символы. Компилятору просто проще. Обычно искажение кодирует что-то, связанное со списком или типами параметров, поскольку это наиболее частые причины необходимости искажения.

C не искажает. Область видимости используется для управления доступом к локальным и глобальным переменным с одинаковым именем.

5
ответ дан 29 November 2019 в 01:10
поделиться

Mangling - это просто то, как компилятор делает счастливым компоновщика.

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

В C++ вы можете иметь две функции с одинаковыми именами, если у них разные типы параметров. Поэтому C++ объединяет имя функции с типами каким-то образом. Таким образом компоновщик воспринимает их как разные имена.

Обратите внимание, что не имеет значения, как именно имя будет искажено, и на самом деле каждый компилятор делает это по-своему. Важно лишь то, что каждая функция с одинаковым базовым именем каким-то образом становится уникальной для компоновщика.

Теперь вы видите, что добавление пространств имен и шаблонов продолжает расширять этот принцип.

18
ответ дан 29 November 2019 в 01:10
поделиться

Технически это «украшение». Это звучит менее грубо, но в то же время подразумевает, что CreditInterest может быть преобразован в IntCrederestit , тогда как то, что происходит на самом деле, больше похоже на _CreditInterest @ 4 , что справедливо для говорят, "украшены" больше, чем покалечены. Тем не менее, я тоже называю это искажением :-), но вы найдете больше технической информации и примеров, если будете искать «украшение имени C ++».

9
ответ дан 29 November 2019 в 01:10
поделиться