Вопросы о звонках - PullRequest
       3

Вопросы о звонках

1 голос
/ 11 ноября 2010

Я помню давно, когда я использовал Turbo C, мне не нужно было заботиться о соглашении о вызове функции, каждая функция, которую я использовал или определяла, принимала форму C соглашения о вызове .

Но после того, как я перешел на платформу Windows, я обнаружил, что существует так много спецификаторов соглашений о вызовах, таких как:

WINAPI, STDCALL, __cdecl ...

Это результат эволюции компилятора?

Ответы [ 5 ]

6 голосов
/ 11 ноября 2010

Нет, это просто или в основном историческое наследие с Windows API. Большинство систем за пределами Windows обычно не используют разные соглашения о вызовах (исключение: системные вызовы и режим ядра).

5 голосов
/ 11 ноября 2010

Различные соглашения о вызовах имеют разные характеристики, а иногда и разные функции, которые могут понадобиться используемому языку или API. Проверьте эту статью для обзора различных соглашений о вызовах, и какие API обычно их используют.

1 голос
/ 11 ноября 2010

WINAPI, STDCALL, ect ... не являются соглашениями о вызовах, они являются макросами, которые определяют соглашения о вызовах. В действительности существует только два или три фактических типа. Причина макросов в обратной совместимости.

0 голосов
/ 19 ноября 2010

Соглашение о вызовах ОЧЕНЬ важно, но вам редко приходится задумываться.

Это становится актуальным при нацеливании на другие ОС или объекты \ библиотеки, написанные на других языках (например, на паскале или около того).

Он определяет, какие и как параметры помещаются в стек (вызывающей стороной) и кто отвечает за извлечение этих параметров из стека при возврате вызываемой функции.

Поскольку C \ C ++ поддерживает список переменных параметров, вызывающая сторона должна вытолкнуть стек (так как вызываемый не знает, сколько ему передано параметров).

Следовательно, это приводит к большому сгенерированному коду (каждый вызов функции расширяется с помощью кода pop-stack).

Однако языки, которые изначально не допускают списки переменных параметров, могут взять на себя бремя вытягивания самого стека из де вызываемой функции (они всегда знают, как она вызывается). В результате получается только один фрагмент кода, извлекаемого из стека (в конце вызываемого абонента), и, следовательно, генерируется меньше кода.

Более того, язык может выбирать способ размещения параметров в стеке. Он может выбирать параметры в том же порядке, в каком они записаны в вызове (первый параметр первым, последний параметр последним) или он может выбрать последний параметр первым и последний параметр последним (как это делает C \ C ++). Последнее позволяет «легко» реализовать список переменных параметров.

если вы не используете переменный список параметров, вы можете выбрать другое соглашение о вызовах по умолчанию (например, PASCAL). Однако это означает, что каждая функция, для которой не указано соглашение о вызовах, будет обрабатываться с выбранным соглашением. Если объявления не совпадают с их реализацией, вы, вероятно, получите неразрешенные внешние ошибки (в лучшем случае) или серьезные ошибки времени выполнения или (в худшем случае) ошибочные вычисления.

В качестве практического примера: Я работал программистом для производителя мобильных компьютеров. Они использовали специальный (ограниченный) компилятор для генерации компактного кода (у мобильного компьютера была очень ограниченная память), поскольку MSVC генерировал большие объекты.

Я предложил изменить соглашение c-call на соглашение pascal-call и некоторые другие незначительные изменения. С тех пор они могли бы использовать более сложный компилятор (MSVC) и делать намного больше.

0 голосов
/ 11 ноября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...