What is the difference between wmain and main?
"If your code adheres to the Unicode programming model, you can use the wide-character version of main, which is wmain."
http://msdn.microsoft.com/en-us/library/aa299386%28VS.60%29.aspx
main( int argc, char *argv[ ], char *envp[ ] )
{
program-statements
}
wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] )
{
program-statements
}
What is the difference between _tmain() and main() in C++?
_tmain
does not exist in C++. main
does.
_tmain
is a Microsoft extension.
main
is, according to the C++ standard, the program's entry point.
It has one of these two signatures:
int main();
int main(int argc, char* argv[]);
Microsoft has added a wmain which replaces the second signature with this:
int wmain(int argc, wchar_t* argv[]);
And then, to make it easier to switch between Unicode (UTF-16) and their multibyte character set, they've defined _tmain
which, if Unicode is enabled, is compiled as wmain
, and otherwise as main
.
As for the second part of your question, the first part of the puzzle is that your main function is wrong. wmain
should take a wchar_t
argument, not char
. Since the compiler doesn't enforce this for the main
function, you get a program where an array of wchar_t
strings are passed to the main
function, which interprets them as char
strings.
Now, in UTF-16, the character set used by Windows when Unicode is enabled, all the ASCII characters are represented as the pair of bytes \0
followed by the ASCII value.
And since the x86 CPU is little-endian, the order of these bytes are swapped, so that the ASCII value comes first, then followed by a null byte.
And in a char string, how is the string usually terminated? Yep, by a null byte. So your program sees a bunch of strings, each one byte long.
In general, you have three options when doing Windows programming:
- Explicitly use Unicode (call wmain, and for every Windows API function which takes char-related arguments, call the
-W
version of the function. Instead of CreateWindow, call CreateWindowW). And instead of usingchar
usewchar_t
, and so on - Explicitly disable Unicode. Call main, and CreateWindowA, and use
char
for strings. - Allow both. (call _tmain, and CreateWindow, which resolve to main/_tmain and CreateWindowA/CreateWindowW), and use TCHAR instead of char/wchar_t.
The same applies to the string types defined by windows.h:
LPCTSTR resolves to either LPCSTR or LPCWSTR, and for every other type that includes char or wchar_t, a -T- version always exists which can be used instead.
Note that all of this is Microsoft specific. TCHAR is not a standard C++ type, it is a macro defined in windows.h. wmain and _tmain are also defined by Microsoft only.
WINMAIN and main() in C++ (Extended)
About the functions.
The C and C++ standards require any program (for a “hosted” C or C++ implementation) to have a function called main
, which serves as the program's startup function. The main
function is called after zero-initialization of non-local static variables, and possibly but not necessarily (!, C++11 §3.6.2/4) this call happens after dynamic initialization of such variables. It can have one of the following signatures:
int main()
int main( int argc, char* argv[] )
plus possible implementation-defined signatures (C++11 §3.6.1/2) except that the result type must be int
.
As the only such function in C++ main
has a default result value, namely 0. If main
returns then after the ordinary function return exit
is called with the main
result value as argument. The standard defines three values that guaranteed can be used: 0 (indicates success), EXIT_SUCCESS
(also indicates success, and is typically defined as 0), and EXIT_FAILURE
(indicates failure), where the two named constants are defined by the <stdlib.h>
header which also declares the exit
function.
The main
arguments are intended to represent the command line arguments for the command used to start the process. argc
(argument count) is the number of items in the argv
(argument values) array. In addition to those items argv[argc]
is guaranteed to be 0. If argc
> 0 – which is not guaranteed! – then argv[0]
is guaranteed to either be a pointer to an empty string, or a pointer to the “name used to invoke the program”. This name may include a path, and it may be the name of the executable.
Using the main
arguments to obtain the command line arguments works fine in *nix, because C and C++ originated with *nix. However, the de facto Windows standard for the encoding of the main
arguments is Windows ANSI, which does not support general Windows filenames (such as, for a Norwegian Windows installation, filenames with Greek or Cyrillic characters). Therefore Microsoft chose to extend the C and C++ languages with a Windows-specific startup function called wmain
, which has wide character based arguments encoded as UTF-16, which can represent any filename.
The wmain
function can have one of these signatures, corresponding to the standard signatures for main
:
int wmain()
int wmain( int argc, wchar_t* argv[] )
plus a few more that are not especially useful.
I.e., wmain
is a direct wide character based replacement for main
.
The WinMain
char
based function was introduced with Windows, in the early 1980's:
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);
where CALLBACK
, HINSTANCE
and LPSTR
are defined by the <windows.h>
header (LPSTR
is just char*
).
Arguments:
the
hInstance
argument value is the base address of the memory image of the executable, it's primarily used to load resources from the executable, and it can alternatively be obtained from theGetModuleHandle
API function,the
hPrevInstance
argument is always 0,the
lpCmdLine
argument can alternatively be obtained from theGetCommandLine
API function, plus a bit of weird logic to skip the program name part of the command line, andthe
nCmdShow
argument value can alternatively be obtained from theGetStartupInfo
API function, but with modern Windows the first creation of a top level window does that automatically so it's not of any practical use.
Thus, the WinMain
function has the same drawbacks as standard main
, plus some (in particular the verbosity and being non-standard), and no advantages of its own, so it's really inexplicable except possibly as a vendor lock-in thing. However, with the Microsoft tool chain it makes the linker default to the GUI subsystem, which some see as an advantage. But with e.g. the GNU toolchain it does not have such an effect so this effect cannot be relied on.
The wWinMain
wchar_t
based function is a wide character variant of WinMain
, in the same way as wmain
is a wide character variant of standard main
:
int WINAPI wWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PWSTR lpCmdLine,
int nCmdShow
);
where WINAPI
is the same as CALLBACK
, and PWSTR
is simply wchar_t*
.
There is no good reason to use any of the non-standard functions except the least known and least supported of them, namely wmain
, and then just for convenience: that this avoids using the GetCommandLine
and CommandLineToArgvW
API functions to pick up UTF-16 encoded arguments.
To avoid the Microsoft linker acting up (the GNU toolchain's linker doesn't), just set the LINK
environment variable to /entry:mainCRTStartup
, or specify that option directly. This is the Microsoft runtime library entry point function that, after some initialization, calls the standard main
function. The other startup functions have corresponding entry point functions named in the same systematic way.
Examples of using the standard main
function.
Common source code:
foo.cpp
#undef UNICODE
#define UNICODE
#include <windows.h>
int main()
{
MessageBox( 0, L"Press OK", L"Hi", MB_SETFOREGROUND );
}
In the examples below (first with the GNU toolchain and then with the Microsoft toolchain) this program is first built as a console subsystem program, and then as a GUI subsystem program. A console subsystem program, or in short just a console program, is one that requires a console window. This is the default subsystem for all Windows linkers I've used (admittedly not a great many), possibly for all Windows linkers period.
For a console program Windows creates a console window automatically if needed. Any Windows process, regardless of subsystem, can have an associated console window, and at most one. Also, the Windows command interpreter waits for a console program program to finish, so that the program's text presentation has finished.
Conversely, a GUI subsystem program is one that doesn't require a console window. The command interpreter does not wait for a GUI subsystem program, except in batch files. One way to avoid the completion wait, for both kinds of program, is to use the start
command. One way to present console window text from a GUI subsystem program is to redirect its standard output stream. Another way is to explicitly create a console window from the program's code.
The program's subsystem is encoded in the executable's header. It's not shown by Windows Explorer (except that in Windows 9x one could “quick view” an executable, which presented just about the same information as Microsoft's dumpbin
tool now does). There is no corresponding C++ concept.
main
with the GNU toolchain.
[D:\dev\test]
> g++ foo.cpp
[D:\dev\test]
> objdump -x a.exe | find /i "subsys"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000003 (Windows CUI)
[544](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[612](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000003 __subsystem__
[636](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> g++ foo.cpp -mwindows
[D:\dev\test]
> objdump -x a.exe | find /i "subsys"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000002 (Windows GUI)
[544](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[612](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000002 __subsystem__
[636](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> _
main
with Microsoft's toolchain:
[D:\dev\test]
> set LINK=/entry:mainCRTStartup
[D:\dev\test]
> cl foo.cpp user32.lib
foo.cpp
[D:\dev\test]
> dumpbin /headers foo.exe | find /i "subsys"
6.00 subsystem version
3 subsystem (Windows CUI)
[D:\dev\test]
> cl foo.cpp /link user32.lib /subsystem:windows
foo.cpp
[D:\dev\test]
> dumpbin /headers foo.exe | find /i "subsys"
6.00 subsystem version
2 subsystem (Windows GUI)
[D:\dev\test]
> _
Examples of using Microsoft’s wmain
function.
The following main code is common to both the GNU toolchain and Microsoft toolchain demonstrations:
bar.cpp
#undef UNICODE
#define UNICODE
#include <windows.h>
#include <string> // std::wstring
#include <sstream> // std::wostringstream
using namespace std;
int wmain( int argc, wchar_t* argv[] )
{
wostringstream text;
text << argc - 1 << L" command line arguments:\n";
for( int i = 1; i < argc; ++i )
{
text << "\n[" << argv[i] << "]";
}
MessageBox( 0, text.str().c_str(), argv[0], MB_SETFOREGROUND );
}
wmain
with the GNU toolchain.
The GNU toolchain doesn't support Microsoft's wmain
function:
[D:\dev\test]
> g++ bar.cpp
d:/bin/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.1/../../../libmingw32.a(main.o):main.c:(.text.startup+0xa3): undefined reference to `WinMain
@16'
collect2.exe: error: ld returned 1 exit status
[D:\dev\test]
> _
The link error message here, about WinMain
, is because the GNU toolchain does support that function (presumably because so much ancient code uses it), and searches for it as a last resort after failing to find a standard main
.
However, it's trivial to add a module with a standard main
that calls the wmain
:
wmain_support.cpp
extern int wmain( int, wchar_t** );
#undef UNICODE
#define UNICODE
#include <windows.h> // GetCommandLine, CommandLineToArgvW, LocalFree
#include <stdlib.h> // EXIT_FAILURE
int main()
{
struct Args
{
int n;
wchar_t** p;
~Args() { if( p != 0 ) { ::LocalFree( p ); } }
Args(): p( ::CommandLineToArgvW( ::GetCommandLine(), &n ) ) {}
};
Args args;
if( args.p == 0 )
{
return EXIT_FAILURE;
}
return wmain( args.n, args.p );
}
Now,
[D:\dev\test]
> g++ bar.cpp wmain_support.cpp
[D:\dev\test]
> objdump -x a.exe | find /i "subsystem"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000003 (Windows CUI)
[13134](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[13576](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000003 __subsystem__
[13689](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> g++ bar.cpp wmain_support.cpp -mwindows
[D:\dev\test]
> objdump -x a.exe | find /i "subsystem"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000002 (Windows GUI)
[13134](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[13576](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000002 __subsystem__
[13689](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> _
wmain
with Microsoft’s toolchain.
With Microsoft's toolchain the linker automatically infers the wmainCRTStartup
entry point if no entry point is specified and a wmain
function is present (it's unclear what happens if a standard main
is also present, I haven't checked that in recent years):
[D:\dev\test]
> set link=/entry:mainCRTStartup
[D:\dev\test]
> cl bar.cpp user32.lib
bar.cpp
LIBCMT.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
bar.exe : fatal error LNK1120: 1 unresolved externals
[D:\dev\test]
> set link=
[D:\dev\test]
> cl bar.cpp user32.lib
bar.cpp
[D:\dev\test]
> _
With a non-standard startup function such as wmain
it is, however, probably best to specify the entry point explicitly, so as to be very clear about the intention:
[D:\dev\test]
> cl bar.cpp /link user32.lib /entry:wmainCRTStartup
bar.cpp
[D:\dev\test]
> dumpbin /headers bar.exe | find /i "subsystem"
6.00 subsystem version
3 subsystem (Windows CUI)
[D:\dev\test]
> cl bar.cpp /link user32.lib /entry:wmainCRTStartup /subsystem:windows
bar.cpp
[D:\dev\test]
> dumpbin /headers bar.exe | find /i "subsystem"
6.00 subsystem version
2 subsystem (Windows GUI)
[D:\dev\test]
> _
WinMain vs. main (C++)
Talking about the Microsoft toolchain, conventionally, Win32 graphical applications have always started with WinMain
, while main
is used for console applications.
The difference between the two kinds of applications actually boils down (mostly) to a single setting in the executable, and is not in capability - a GUI application can create a console, and a console application can create a window - but in the behavior of the loader: for an exe marked as GUI the loader won't allocate any console, while a console exe will attach to the parent's console or create a new one if there isn't one.
For the entrypoint name, it is all just a matter of linker/CRT defaults: the "real" entry point of the executable is just an offset into the final executable, that points to a function that takes no parameters. It's the CRT that does its stuff, determines the parameters and then calls "your" entrypoint, so, in line of principle, they both could work exactly the same way.
The point is, the name/signature of the default entrypoint that the CRT looks for depends from the type of application you are building; if the compiler and linker are set to build a console application, they will look for a main
(or wmain
or _tmain
, depending on Unicode settings), for a GUI application they use WinMain
, and DllMain
for a dll.
So:
- use
WinMain
if you are building a GUI (=no console created for it at startup) application; main
for a console application;DllMain
for a dll.
Again, this all isn't written in stone (and there are ways to start a GUI application from a standard main
), but "when in Rome, do as the Romans do" - i.e. it's usually best to follow the uses of the platform to avoid confusing other developers and going through untested/unsupported compiler settings just to change the signature of the entrypoint.
wmain vs main C runtime
Modern versions of Windows internally use UTF-16. Therefore, when you launch an executable, all command line arguments likely are passed as UTF-16 from the onset, and the runtime library linked into the launched application either passes the arguments through unscathed (if using wmain
) or converts them to the local encoding automatically (if using main
). (Specifically this would be done by wmainCRTStartup
/mainCRTStartup
which are the actual entry points used for console Windows applications.)
What are, and what is the difference between, kmain and dmain -- main functions in C?
You seem to be referring to this tutorial on OSDev.org.
If you’ll notice, this is not a standard C program with main()
as its entry point. In fact, the page shows two entry points: one written in Assembler in a way for GRUB to find & load, and which sets up & loads the second, kmain()
, which is written in C. The writers use the name kmain
to mean “kernel main”; presumably dmain
is the entry point for drivers & would stand for “driver main”.
C makes a distinction between “freestanding” and “hosted” implementations. Hosted is what you’re probably more familiar with; the standard C library is available, and all programs start at the main
function.
OS kernels are (often) good examples of freestanding environments. The C library will likely not be available, for example (except for certain headers like stddef.h
& stdarg.h
; see the standard for details). Also, the entry point is not defined by the standard anymore. The OSDev.org tutorial is making a special point of that fact, by explicitly defining its entry point with a different name.
You could probably run the tutorial renaming kmain
to main
, but note that it’s still void main(void*, unsigned int)
, not int main(int, char**)
; in fact that sort of confusion is likely part of the reason the writers chose to use a different name. But is is just a convention they’ve selected, not anything standardized.
How to force the visual studio to use the wmain instead of main
Using the #pragma comment(linker, "/SUBSYSTEM:CONSOLE /ENTRY:mainCRTStartup")
You are getting close, not quite close enough. The CRT has four entrypoints:
- mainCRTStartup => calls main(), the entrypoint for console mode apps
- wmainCRTStartup => calls wmain(), as above but the Unicode version
- WinMainCRTStartup => calls WinMain(), the entrypoint for native Windows apps
- wWinMainCRTStartup => calls wWinMain(), as above but the Unicode version
So it is /ENTRY:wmainCRTStartup
Do beware that the command line arguments are converted to Unicode assuming the default console code page. Which is a bit unpredictable, it is the legacy 437 OEM code page only in Western Europe and the Americas. The user might need to use the CHCP command (CHange Code Page) and tinker with the console window font to keep you happy. YMMV.
Can we use wmain() with Unix compilers or it'll work only on Windows?
The only standard signatures for main
are:
int main(void);
int main(int argc, char *argv[]);
However, a freestanding implementation can provide extensions/allow other signatures. But those are not guranteed to be portable. wmain
looks like a Windows/VS thing. There's not much chance this will work on a *nix/GNU GCC.
C++ main vs C main
Both C and C++ require that any implementation of the language must support the forms int main(void)
and int main(int, char**)
. However, the standards also say that additional forms may be supported by the implementation, and thus a program that uses one of those other forms is not automatically invalid -- rather, it is a valid program that only happens to be supported on certain platforms.
The only difference between C and C++ in that regard is which alternative forms of main
are permitted. In C++, all forms must return int
, so only the arguments are allowed to vary, and moreover, if the first two arguments of any form are int, char**
, they should have the usual meaning.
C is a little more liberal, as it allows any alternative form of main
. Thus a program with void main(char, double)
is a valid C program that requires the implementation to support this signature, while it would unconditionally be ill-formed C++. On the other hand, int main(int, char**, char**)
is a permissible signature for both C and C++, also requiring implementation support, and C++ would expect the first two arguments to have the usual meaning.
Related Topics
Explicit Type Conversion and Multiple Simple Type Specifiers
C++ Get Description of an Exception Caught in Catch(...) Block
Dangling References and Undefined Behavior
C++ Debug Builds Broke in Snow Leopard Xcode
Fastest Way to Produce a Mask with N Ones Starting at Position I
Why How to Call a Non-Constexpr Function Inside a Constexpr Function
How to Take Ownership of an Abandoned Boost::Interprocess::Interprocess_Mutex
Compiling and Linking Third Party Libraries in VS 2015
In Which Versions of the C++ Standard Does "(I+=10)+=10" Have Undefined Behaviour
Partial Specialization of Function Templates
Why Is a C++ Bool Var True by Default
C++ Class or Struct Compatiblity with C Struct
How to See the Output of the Visual C++ Preprocessor
How to Handle a Ctrl-Break Signal in a Command Line Interface