Почему изменение имени используется с функцией WinMain ()?

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

Но я заметил, что изменение имени также используется с функцией WinMain() (которая не перегружена). После изменения имени он становится _WinMain@16.

Итак, почему изменение имени используется с функцией WinMain()?


Это код, который я использовал:

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{

    return 0;
}

person Steve    schedule 06.07.2017    source источник
comment
Если бы компилятор на самом деле действительно исказил символ WinMain, это было бы совсем не так, как вы видите. Вы видите, что компилятор имеет особую обработку символа WinMain.   -  person Some programmer dude    schedule 06.07.2017
comment
Я считаю, что _WinMain@16 - это какое-то внутреннее имя, используемое компилятором mingw / gcc. Что должно означать 16, я понятия не имею.   -  person Lundin    schedule 06.07.2017
comment
@Lundin @ означает stdcall соглашение о вызовах, 16 - это размер списка параметров (здесь: 4 раза 4-байтовый аргумент). Функции, использующие другие соглашения о вызовах, оформлены по-другому.   -  person    schedule 06.07.2017
comment
@FelixPalmen Ой, я этого не знала! На самом деле это означает совершенный смысл. Хотя, как в таком случае вызывающий абонент узнает о типе возвращаемого значения? По логике вещей, не лучше ли это быть 4_WinMain@16 или _WinMain@20 или что-то в этом роде? И это определяется ABI или Mingw?   -  person Lundin    schedule 06.07.2017
comment
@Lundin с cdecl, вам вообще не нужна информация о размере списка аргументов, и я недостаточно глубоко разбираюсь в различных соглашениях о вызовах, доступных в Windows, но, похоже, компоновщикам нужно знать только размер аргументов для stdcall ...;)   -  person    schedule 06.07.2017
comment
C не использует изменение имени.   -  person too honest for this site    schedule 06.07.2017
comment
@ Олаф, вроде как. Дайте одно и то же имя нескольким статическим переменным в разных областях видимости и посмотрите, что произойдет.   -  person Lundin    schedule 06.07.2017
comment
Это не искажение имени, это украшение имени. Искажение - это концепция C ++.   -  person David Heffernan    schedule 06.07.2017
comment
@FelixPalmen Очевидно, соглашение о вызове cdecl не допускает никаких других типов возвращаемых значений, кроме одного регистра (4 байта), регистра 0. Итак, я полагаю, что если вы попытаетесь вернуть двойной или какой-то другой, компилятор должен будет передать часть это через параметры за строками.   -  person Lundin    schedule 06.07.2017
comment
@Lundin Буду признателен за ссылку на стандарт. Примечание: я не говорил о конкретной реализации. О символах с внутренней связью: в этом нет необходимости. Хотя это может быть вспомогательным средством отладки.   -  person too honest for this site    schedule 06.07.2017
comment
@Olaf Это не стандартизировано. Но очевидно, что компилятор, столкнувшийся с 50 переменными, все называемые foo, должен будет использовать какой-то способ изменения имен - в значительной степени определяемый реализацией.   -  person Lundin    schedule 06.07.2017
comment
Нет. Компилятор не допускает переопределения такого рода.   -  person too honest for this site    schedule 06.07.2017
comment
@DavidHeffernan согласно wikipedia, изменение имени и украшение имени - это два названия для одного и того же. Есть ли у вас какие-либо официальные ссылки на то, что искажение имен является единственной вещью на C ++?   -  person davmac    schedule 06.07.2017
comment
@Olaf, если они находятся в разных сферах, это не переопределение. И, конечно же, нет необходимости создавать символьные имена для объектов с внутренней связью. Компиляторы до сих пор это делают.   -  person    schedule 06.07.2017
comment
@davmac эти термины не определены стандартом, поэтому есть некоторая двусмысленность в их использовании. Тем не менее, то, что вы обычно подразумеваете под искажением имени, - это то, что компиляторы C ++ делают для создания имен символов, включающих все виды информации, поэтому перегруженные функции различимы. То, что показано здесь (просто добавление небольшой информации о соглашении о вызовах), обычно называется украшением. Но об условиях можно, наверное, много спорить;)   -  person    schedule 06.07.2017
comment
@FelixPalmen. Различные области видимости решаются с помощью простого стека, соответственно. иерархическая (для структуры / объединения) таблица символов.   -  person too honest for this site    schedule 06.07.2017
comment
@Olaf Я получаю, например, x.1276 и x.1279 для двух static int x;, определенных в разных областях. Компиляторы могут делать что угодно для именования этих символов.   -  person    schedule 06.07.2017
comment
@FelixPalmen: Это ваша реализация, а не требование языка или чего-то еще. Из моего 1-го комментария: я не говорил о конкретной реализации. О символах с внутренней связью: в этом нет необходимости. Хотя это может быть вспомогательным средством отладки.   -  person too honest for this site    schedule 06.07.2017
comment
@Olaf, и это неуместно для вопроса, почему это происходит? C имеет аспекты, определяемые реализацией, и сейчас мы в основном обсуждаем ABI.   -  person    schedule 06.07.2017
comment
@FelixPalmen, которые не являются частью стандарта C. Следовательно, тег C неверен.   -  person too honest for this site    schedule 06.07.2017
comment
Пожалуйста, остановитесь, двигая вперед-назад над тегом [c]. С этим не стоит бороться, и если вы хотите обсудить, является ли это подходящим тегом, пожалуйста, отправьте его в чат или в Meta.   -  person Brad Larson    schedule 06.07.2017
comment
@Davmac Википедия не говорит о C ++. Конечно, здесь, в Windows, мы делаем это различие.   -  person David Heffernan    schedule 06.07.2017
comment
@DavidHeffernan В нем конкретно перечислены примеры для C и C ++, а примеры C - это именно то, о чем спрашивает OP, и конкретно упоминаются там как искажение имен. Хотя Википедия на самом деле не является авторитетным источником, я считаю, что если вы хотите заявить, что терминология OP неверна, вы должны сделать это авторитетно (или просто признать, что не все всегда используют одни и те же слова одинаково - википедия показывает, что < i> кто-то с вами не согласен).   -  person davmac    schedule 07.07.2017


Ответы (1)


Это не то, что обычно называют изменением имени. Изменение имен предназначено для C ++ для создания отличительных имен символов из функций с тем же именем (и, к сожалению, это определяется реализацией). Здесь у вас есть простое "оформленное имя" по правилам Win32 ABI. Windows использует их, чтобы скрыть различные соглашения о вызовах, доступные на этой платформе.

В этом случае одиночный @ обозначает stdcall соглашение о вызовах, а следующее за ним число - количество байтов в списке аргументов. Макрос WINAPI расширяется до некоторого специфичного для компилятора атрибута, который выбирает stdcall в качестве соглашения о вызовах.

В разных ABI используются разные украшения имен. Например. в Linux ваше стандартное соглашение о вызовах - cdecl, и оно вообще не использует никаких украшений. Но у вас могут быть украшения, содержащие версию символа (по совпадению после знака @)

person Community    schedule 06.07.2017
comment
В этом случае одиночный @ обозначает соглашение о вызовах stdcall Не только @ обозначает соглашения о вызовах stdcall (поскольку соглашение о вызовах fastcall также использует @). Соглашение о вызовах stdcall обозначает верхнее подчеркивание, а также @ и число после @, которое представляет количество байтов для параметров. - person James; 06.07.2017