cdecl — что означает «#define __cdecl» в моем коде C ++?

Я работаю над существующим проектом C ++ с Visual Studio, и я обнаружил, что почти каждое объявление функции получает __cdecl перед именем функции, например:void __cdecl functionName(), Затем я перехожу к определению __cdecl, который находится в winnt.h файл:

#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define NTAPI __stdcall
#else
#define _cdecl
#define __cdecl
#define NTAPI
#endif

Я искал Cdecl и получил, что это соглашение о вызовах по умолчанию для программ на C и C ++, но код выше говорит мне, что __cdecl не распространяется ни на что. Так зачем ставить __cdecl перед именем функции, так как это просто ничего? или я неправильно понял код выше?

2

Решение

в чем смысл #define __cdecl »

Линии, начинающиеся с # являются директивами препроцессора. #define директива, которая определяет макрос препроцессора. #define __cdecl определяет макрос с идентификатором __cdecl и пустая замена. Если такой макрос определен, процессор заменит все экземпляры __cdecl с пустой строкой.

Так зачем помещать __cdecl перед именем функции, поскольку это просто ничего?

Взгляните на директивы в начале рассматриваемого определения:

#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#else

Макрос определен условно. Когда макрос не определен, __cdecl не расширится ни к чему. Когда не расширены до нуля, __cdecl это специфический для Microsoft спецификатор функции, как вы обнаружили.

Условно определенный макрос позволяет писать код, который использует __cdecl в системах, которые позволяют это, и автоматически удаляют это в системах, которые этого не делают.

Но я все еще путаюсь с #if (_MSC_VER> = 800) || определенная (_STDCALL_SUPPORTED) строка, что это значит?

Это директива препроцессора, которая проверяет, является ли макрос _MSC_VER имеет большее значение, чем 800, или, если макрос _STDCALL_SUPPORTED определено. Если тест ложен, то код между #if и #else удаляется. Если это правда, то код между #else и #endif удаляется.

0

Другие решения

Это означает, что если API определен как использующий NTAPI, он сгенерирует код, который использует соглашение о вызовах __stdcall — разновидность соглашения о вызовах Pascal, в котором вызываемый объект очищает стек. С __cdecl вызывающая сторона очищает стек (поэтому он поддерживает функции с переменным типом).

И все это зависит от #if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)

0