Я добавлю еще один ответ, чтобы обсудить некоторые из тангенциальных дискуссий, которые имели место.
C ABI (прикладной двоичный интерфейс), первоначально вызываемый для передачи аргументов в стеке в обратном порядке (т. Е. - нажатый справа налево), где вызывающий объект также освобождает хранилище стека. Современная ABI фактически использует регистры для передачи аргументов, но многие из соображений о переходе возвращаются к тому, что передается исходный аргумент стека.
Оригинальный Pascal ABI, напротив, подтолкнул аргументы слева направо, и вызываемому пришлось выставить аргументы. Оригинальный C ABI превосходит оригинальный Pascal ABI в двух важных точках. Аргумент push order означает, что смещение стека первого аргумента всегда известно, позволяя функции, которые имеют неизвестное количество аргументов, где ранние аргументы управляют количеством других аргументов (ala printf
).
Второй способ, с помощью которого C ABI является превосходным, - это поведение, если вызывающий и вызываемый не согласны с тем, сколько аргументов существует. В случае C, если вы фактически не получаете доступа к аргументам за последний, ничего плохого не происходит. В Pascal из стека выводится неправильное количество аргументов, и весь стек поврежден.
Оригинальный Windows 3.1 ABI был основан на Паскале. Как таковой, он использовал Pascal ABI (аргументы в порядке слева направо, вызываемые позывы). Поскольку любое несоответствие в аргументе может привести к повреждению стека, была создана схема переключения. Каждое имя функции исказилось с номером, указывающим размер в байтах его аргументов.Так, на 16-битной машине, следующая функция (синтаксис C):
int function(int a)
был подогнан к [email protected]
, потому что int
два байта в ширине. Это было сделано так, что если объявление и определение не совпадают, компоновщик не сможет найти функцию, а не повреждает стек во время выполнения. И наоборот, если ссылки программы, то вы можете быть уверены, что правильное количество байт выставляется из стека в конце вызова.
32-битные Windows и последующие используют вместо этого ABI stdcall
. Он похож на Pascal ABI, за исключением того, что порядок push похож на C, справа налево. Как и Pascal ABI, имя mangling искажает размер байта аргументов в имени функции, чтобы избежать повреждения стека.
В отличие от утверждений, сделанных в другом месте здесь, C ABI не изменяет имена функций даже в Visual Studio. И наоборот, функции управления, декорированные спецификацией ABI stdcall
, не уникальны для VS. GCC также поддерживает этот ABI, даже при компиляции для Linux. Это широко используется Wine, в котором используется собственный загрузчик, чтобы обеспечить возможность компоновки исполняемых файлов из Linux в скомпилированные DLL-файлы Windows.
C не нуждается в том, чтобы заманить имена, потому что у него нет функции перегрузки. – EOF
Как вы связываете библиотеки C с кодом C++, если компилятор C++ управляет именами функций? – Mat
, но что неправильно, позволяя компилятору просто калечить их в любом случае? Почему это повлияет на нашу программу? Тогда нам не понадобится extern «C». – Engineer999