Fog Creek Software
Discussion Board

Hiding my ignorance about C syntax

Have you ever not understood something, but waited too long to ask? That is, if you had asked someone at the beginning, the question would have seemed natural, but you've waited too long, so you'd lose face.

That's how I feel about the C syntax in some function calls. For example in Win32 programming there's "int WINAPI WinMain()".  If "int" is the return type and "WinMain" is the function name, then what the hell is "WINAPI"?

I've never seen this syntax in K&R or any other C/C++ book I have, so I've never been able to figure it out.

What the hell is that?

Saturday, June 14, 2003

Looks like a macro ;) don't know what it's defined as though. I don't do Win32 any.

Always ask when it hits you. Always. Or look it up. But never, *ever* let things go for any kind of time period.

Sometime's I'll let things go if I am relatively certain they aren't important, for instance yesterday I was working on some PHP3/MySQL code. I haven't worked with either in *years*, and my knowledge has grown to be a bit spotty. But, it didn't matter. I ignored my ignorance, and got the job done because the things I didn't understand just plain didn't matter.

By the same token, I always make absolutely sure that I understand the architechture we're working with, etc., because that is knowledge you can't work without. Or at least design without, anyway.

If it matters, always make damned sure you know it. And screw saving face, if you fsck it up, you'll lose a hell of a lot more than just asking the damned question would cost you.

Mike Swieton
Saturday, June 14, 2003

WINAPI is indeed one of the many macros defined in the Platform SDK include files -- if you're confused about any of them you should either search MSDN or the all files in the directory that contains windows.h.

The WINAPI macro is defined in WinDef.h and determines the calling convention. It maps to _stdcall for VC++ which implies the "Pascal" calling convention, i.e. the callee cleans up the stack (IIRC).

Chris Nahr
Saturday, June 14, 2003

WINAPI is a macro defined in windef.h as

#define WINAPI      __stdcall

__stdcall itself is a Microsoft extension to the C language which states this C function is responsible for cleaning up its own stack when it exits (instead of having the calling function cleaning up the stack, as what usually happens).

There's no good reason for this; it's just due to a design decision made in Windows back in the day and one we can't change now.

Saturday, June 14, 2003

It does look like a macro.  Run it through the preprocessor (if you can do that.  I am a C/C++ programmer, but not Win32)  and see what you get.  WINAPI may be defined to be a null string and only be there as a flag for the user or for grepping the source files.  And, hopefully, a Win32 programmer will come along and tell us what it is really for.

Saturday, June 14, 2003

>>> hopefully, a Win32 programmer will come along <<<

Which happened while I was typing my response.  Well, now you know why K&R and your other books didn't have anything to say about it.

Saturday, June 14, 2003

> There's no good reason for this

Actually it makes the compiled code a bit smaller: if there's one 4-byte parameter, for example, then the single callee will end with a "RET 4" opcode, instead of every caller needing an extra "ADD SP,4" after the subroutine call. It's used for most functions, except for functions like wsprintf() where only the caller knows for sure how many parameters it pushed.

Christopher Wells
Saturday, June 14, 2003

Isn't _stdapi also the same as the Pascal calling syntax? It's been a long time...

Note than in Visual Studio, you can ask it where anything is defined by selecting 'go to definition' or some such off the context menu (and some other places). You may have to let it build a browse file. They let you look at call trees and all sorts of things, anyone know where the equivalent (the features beyond 'show defintion') went off to in VS2003? I haven't found it yet.

Saturday, June 14, 2003

I think the only difference betwen WINAPI and Pascal calling convention is that the Pascal calling convention pushes the parameters from left to right.

Saturday, June 14, 2003

>> I think the only difference betwen WINAPI and Pascal calling convention is that the Pascal calling convention pushes the parameters from left to right.

...AND the procedure itself removes the arguments from the stack... NOT the caller, as C calling convention does. As already stated, Pascal convention results in very slightly smaller code.

IE, you *cannot* fake a Pascal calling declaration by simply reversing the order of the passed parameters. The caller of the procedure must be aware at the assembler level that it's calling Pascal proc type.

Hence the function qualifiers, which govern the low level code being emitted by the compiler.

Bored Bystander
Saturday, June 14, 2003

As has been pointed out, WINAPI is translated by the preprocessor to __stdcall. Of course, you can also use __stdcall explicitly in your function declaration:

int __stdcall WinMain()

The reason for the use of WINAPI is that it's also an indication that this function is a part of the Win32 API. There are other macros defined by the Microsoft header files that also translate to __stdcall but are distinct in order to indicate their particular usage, e.g. CALLBACK.

BTW, the double underscore prefix is a standard C/C++ convention to indicate custom language extensions, so MS was playing by the rules here (though code that uses custom extension obviously risks being non-portable).

Like Pascal, __stdcall pushes the arguments in reverse order to __cdecl, the standard C calling convention. And as mentioned above, it's up to the callee to clear the stack instead of the caller. The result is more efficient code, both because there are more instances of the calling code than the code being called, and because of the aforementioned built-in support in x86 assembly for this calling convention.

The reason C/C++ doesn't use this calling convention by default is that __cdecl allows calling functions with a variable number of arguments, e.g. printf. The Win32 API doesn't use this feature (except for the wsprintf function) and for historic reasons (which Joel may know about more than I) uses the Pascal calling convention.

More than you ever wanted to know about WINAPI ;-)

BTW, I wholeheartedly recommend to always ask when you don't understand something. Worst case, you're embarrassed once. The alternative is to carry the embarrassment inside you all the time. And if you want to avoid that one-time embarrassment, try using Google first :-)

Dan Shappir
Saturday, June 14, 2003

I vaguely remember the reason for preferring __stdcall in the Win32 API was that MS did some benchmarking and __stdcall functions ended up being about 10% faster than __cdecl functions. Probably because __stdcall functions can clear the entire stack frame in a single instruction.

No idea if that's still true in this post-pentium era.

Chris Tavares
Sunday, June 15, 2003

The thing Asinorum should be embarassed about is that he or she couldn't figure out how to right click on WINAPI and Go To Definition or hit F1. Help is just a few clicks or keystrokes away.

Sunday, June 15, 2003

According to Petzold in "Programming Windows 3.1", using __stdcall in place of __cdecl shaved the compiled code enough to for MS to bundle 1 fewer diskette in the Windows 1.0 box. Major COG (Cost Of Goods) savings in the days before CD-ROM software distribution.

Phillip Bailey
Monday, June 16, 2003

*  Recent Topics

*  Fog Creek Home