Исторически сложилось, что первые компиляторы C ++ использовали эквивалент __stdcall
.С точки зрения качества реализации, я ожидаю, что компилятор C будет использовать __cdecl
соглашения, а компилятор C ++ - __stdcall
(которые тогда были известны как соглашения Pascal).Это одна вещь, которую ранние компиляторы Zortech получили правильно.
Конечно, функции vararg должны все еще использовать __cdecl
соглашения.Вызываемый не может очистить стек, если он не знает, сколько нужно очистить.
(Обратите внимание, что стандарт C был тщательно разработан, чтобы разрешить также соглашения __stdcall
в C. Я толькооднако известно об одном компиляторе, который воспользовался этим преимуществом: объем существующего в то время кода, который вызывал функции vararg без представления прототипа, был огромен, и хотя стандарт объявил, что он не работает, разработчики компиляторов не хотели ломать своих клиентов'code.)
Во многих средах, кажется, существует очень сильная тенденция настаивать на том, что соглашения C и C ++ совпадают, что можно взять адрес функции extern "C++"
,и передать его функции, написанной на C, которая вызывает его.IIRC, например, g ++ не обрабатывает
extern "C" void f();
и
void f();
как имеющие два разных типа (хотя стандарт требует этого), и позволяет передавать статический адресфункция-член pthread_create
, например.В результате такие компиляторы везде используют одни и те же соглашения, а в Intel они эквивалентны __cdecl
.
Многие компиляторы имеют расширения для поддержки других соглашений.(Почему они не используют стандарт extern "xxx"
, я не знаю.) Однако синтаксис для этих расширений очень разнообразен.Microsoft помещает атрибут непосредственно перед именем функции:
void __stdcall func( int, int );
, g ++ помещает его в специальное предложение атрибута после объявления функции:
void func( int, int ) __attribute__((stdcall));
C ++ 11 добавилстандартный способ указания атрибутов:
void [[stdcall]] func( int, int );
Он не определяет stdcall
как атрибут, но действительно указывает, что дополнительные атрибуты (отличные от определенных в стандарте) могутбыть указанным и зависит от реализации.Я ожидаю, что и g ++, и VC ++ принимают этот синтаксис в своих последних версиях, по крайней мере, если C ++ 11 активирован.Однако точное имя атрибута (__stdcall
, stdcall
и т. Д.) Может отличаться, поэтому, вероятно, вы захотите обернуть это в макрос.
Наконец: в современном компиляторе с включенной оптимизациейРазница в соглашениях о вызовах, вероятно, незначительна.Такие атрибуты, как const
(не путать с ключевым словом C ++ const
), regparm
или noreturn
, вероятно, окажут большее влияние как с точки зрения размера исполняемого файла, так и производительности.