Это действительно зависит от соглашения о вызовах и архитектуры.Например, при cdecl
на x86, когда аргументы перемещаются справа налево и вызывающий восстанавливает стек, наличие дополнительного параметра прозрачно для функции bar
:
push 11
push 10
call _bar
add esp, 8
bar
только «увидит» 10
и будет работать с этим параметром, как ожидается, возвращая 100
.После этого стек восстанавливается, поэтому в main
также нет смещения;если бы вы только что передали 10
, вместо этого добавили бы 4 к esp
.
Это также относится к соглашениям о вызовах x64 для MSVC в Windows и Система V ABI , где первые несколько 1 целочисленных аргументов передаются в регистрах;второй аргумент будет заполнен в назначенном регистре вызовом в main
, но даже не будет рассмотрен bar
.
Если, однако, вы попытались использовать альтернативное соглашение о вызовах, когда вызываемый абонентОтветственный за очистку стека, вы столкнетесь с проблемами либо на этапе сборки, либо (что еще хуже) во время выполнения.stdcall
, например, украшает имя функции числом байтов, используемых списком аргументов, поэтому я даже не могу связать конечный исполняемый файл, изменив bar
на использование stdcall
вместо этого:
error LNK2019: unresolved external symbol _bar@8 referenced in function _main
Это потому, что bar
теперь имеет сигнатуру _bar@4
в своем объектном файле, как и должно быть.
Это становится интересным, если вы используете устаревшее соглашение о вызовах pascal
, где параметры перемещаются слева направо:
push 10
push 11
call _bar
Теперь bar
возвращает 121, а не 100, как вы ожидали.То есть, если функция успешно вернется, чего не произойдет, поскольку вызываемый объект должен был очистить стек, но потерпел неудачу из-за дополнительного параметра, уничтожив адрес возврата.
1: 4 для MSVC onОкна;6 в системе V ABI