Когда использовать соглашения о вызовах

Каковы ключевые факторы при использовании различных соглашений о вызовах? Когда делает кто-то знает для использования определенных соглашений о вызовах такой как __cdecl или __stdcall или __fastcall в различных случаях.

Примеры были бы действительно apprciated.

6
задан David Weng 4 August 2010 в 11:26
поделиться

1 ответ

В большинстве случаев вам не нужно беспокоиться об этом. Обычно вы будете использовать __ cdecl , но только потому, что это значение по умолчанию в Visual C ++. Однако функции-члены C ++ по умолчанию используют соглашение __ thiscall в Visual C ++

. (Довольно распространенная) ситуация, когда вам действительно нужно беспокоиться о соглашениях о вызовах, когда вы передаете обратные вызовы функциям API, например в Windows API:

// CALLBACK is #define'd as __stdcall 
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg 
    WPARAM wParam, LPARAM lParam); 
// ... 
windowClass.lpfnWndProc = &MyWndProc; 
::RegisterClass(&windowClass);

Здесь мы объявляем MyWndProc () как имеющий соглашение __ stdcall ( CALLBACK is #define ' d как __ stdcall ). Это необходимо, потому что операционная система ожидает, что lpfnWndProc указывает на WNDPROC , , который использует соглашение CALLBACK .

Практически каждая функция Windows API, которая принимает обратный вызов, требует, чтобы функции обратного вызова использовали соглашение __ stdcall , а поскольку __ cdecl обычно используется по умолчанию, вы должны сделать это явным (вы будет использовать CALLBACK для оконных процедур).

Это чрезвычайно важно, поскольку может произойти повреждение стека, если операционная система попытается вызвать функцию, отличную от __ stdcall .К сожалению, достаточно много людей ошибаются в том, что Windows фактически проверяет несоответствие соглашения о вызовах специально для оконных процедур .

Хотя __ stdcall требуется для функций обратного вызова, передаваемых функциям WinAPI, функции, которые принимают переменное количество аргументов, должны использовать соглашение о вызовах __ cdecl , потому что только вызывающий будет знать, как правильно вытолкнуть переменное количество аргументов из стека. Поскольку по умолчанию обычно используется __ cdecl , вам не нужно явно указывать __ cdecl для функций, которые принимают переменное количество аргументов.

Я лично не нашел применения __ fastcall , хотя уверен, что у кого-то есть.

__ clrcall актуально, только если вы взаимодействуете с управляемым кодом.

13
ответ дан 8 December 2019 в 18:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: