{"id":2543,"date":"2013-11-28T07:00:00","date_gmt":"2013-11-28T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/11\/28\/if-you-try-to-declare-a-variadic-function-with-an-incompatible-calling-convention-the-compiler-secretly-converts-it-to-cdecl\/"},"modified":"2013-11-28T07:00:00","modified_gmt":"2013-11-28T07:00:00","slug":"if-you-try-to-declare-a-variadic-function-with-an-incompatible-calling-convention-the-compiler-secretly-converts-it-to-cdecl","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20131128-00\/?p=2543","title":{"rendered":"If you try to declare a variadic function with an incompatible calling convention, the compiler secretly converts it to cdecl"},"content":{"rendered":"<p>\nConsider the following function on an x86 system:\n<\/p>\n<pre>\nvoid __stdcall something(char *, ...);\n<\/pre>\n<p>\nThe function declares itself as <code>__stdcall<\/code>,\nwhich is a callee-clean convention.\nBut a variadic function cannot be callee-clean since the callee\ndoes not know how many parameters were passed,\nso it doesn&#8217;t know how many it should clean.\n<\/p>\n<p>\nThe Microsoft Visual Studio C\/C++ compiler resolves this conflict\nby silently converting the calling convention to <code>__cdecl<\/code>,\nwhich is the only supported variadic calling convention\nfor functions that do not take a hidden <code>this<\/code> parameter.\n<\/p>\n<p>\nWhy does this conversion take place silently rather than generating\na warning or error?\n<\/p>\n<p>\nMy guess is that it&#8217;s to make the compiler options\n<code>\/Gr<\/code> (set default calling convention to <code>__fastcall<\/code>)\nand\n<code>\/Gz<\/code> (set default calling convention to <code>__stdcall<\/code>)\nless annoying.\n<\/p>\n<p>\nAutomatic conversion of variadic functions to <code>__cdecl<\/code>\nmeans that you can just add the <code>\/Gr<\/code> or <code>\/Gz<\/code>\ncommand line switch to your compiler options, and everything will\nstill compile and run (just with the new calling convention).\n<\/p>\n<p>\nAnother way of looking at this is not by thinking of the compiler\nas converting variadic <code>__stdcall<\/code> to <code>__cdecl<\/code>\nbut rather by simply saying\n&#8220;for variadic functions, <code>__stdcall<\/code> is caller-clean.&#8221;\n<\/p>\n<p>\n<b>Exercise<\/b>:\nHow can you determine which interpretation is what the compiler actually does?\nIn other words, is it the case that the compiler converts\n<code>__stdcall<\/code> to <code>__cdecl<\/code> for variadic functions,\nor is it the case that the calling convention for variadic\n<code>__stdcall<\/code> functions is caller-clean?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Consider the following function on an x86 system: void __stdcall something(char *, &#8230;); The function declares itself as __stdcall, which is a callee-clean convention. But a variadic function cannot be callee-clean since the callee does not know how many parameters were passed, so it doesn&#8217;t know how many it should clean. The Microsoft Visual Studio [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-2543","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Consider the following function on an x86 system: void __stdcall something(char *, &#8230;); The function declares itself as __stdcall, which is a callee-clean convention. But a variadic function cannot be callee-clean since the callee does not know how many parameters were passed, so it doesn&#8217;t know how many it should clean. The Microsoft Visual Studio [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2543","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=2543"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2543\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=2543"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=2543"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=2543"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}