C++中_tmain()和main()有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/895827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:49:54  来源:igfitidea点击:

What is the difference between _tmain() and main() in C++?

c++unicodearguments

提问by joshcomley

If I run my C++ application with the following main() method everything is OK:

如果我使用以下 main() 方法运行我的 C++ 应用程序,一切正常:

int main(int argc, char *argv[]) 
{
   cout << "There are " << argc << " arguments:" << endl;

   // Loop through each argument and print its number and value
   for (int i=0; i<argc; i++)
      cout << i << " " << argv[i] << endl;

   return 0;
}

I get what I expect and my arguments are printed out.

我得到了我的期望并且我的论点被打印出来。

However, if I use _tmain:

但是,如果我使用 _tmain:

int _tmain(int argc, char *argv[]) 
{
   cout << "There are " << argc << " arguments:" << endl;

   // Loop through each argument and print its number and value
   for (int i=0; i<argc; i++)
      cout << i << " " << argv[i] << endl;

   return 0;
}

It just displays the first character of each argument.

它只显示每个参数的第一个字符。

What is the difference causing this?

造成这种情况的区别是什么?

回答by jalf

_tmaindoes not exist in C++. maindoes.

_tmain在 C++ 中不存在。main做。

_tmainis a Microsoft extension.

_tmain是微软的扩展。

mainis, according to the C++ standard, the program's entry point. It has one of these two signatures:

main根据 C++ 标准,它是程序的入口点。它具有以下两个签名之一:

int main();
int main(int argc, char* argv[]);

Microsoft has added a wmain which replaces the second signature with this:

微软添加了一个 wmain,它用这个替换了第二个签名:

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 _tmainwhich, if Unicode is enabled, is compiled as wmain, and otherwise as main.

然后,为了更轻松地在 Unicode (UTF-16) 和它们的多字节字符集之间切换,他们定义_tmain了,如果启用了 Unicode,则编译为wmain,否则编译为main.

As for the second part of your question, the first part of the puzzle is that your main function is wrong. wmainshould take a wchar_targument, not char. Since the compiler doesn't enforce this for the mainfunction, you get a program where an array of wchar_tstrings are passed to the mainfunction, which interprets them as charstrings.

至于你的问题的第二部分,谜题的第一部分是你的主要功能是错误的。wmain应该wchar_t争论,而不是char。由于编译器不会对main函数强制执行此操作,因此您会得到一个程序,其中将wchar_t字符串数组传递给main函数,该函数将它们解释为char字符串。

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 \0followed by the ASCII value.

现在,在 UTF-16(启用 Unicode 时 Windows 使用的字符集)中,所有 ASCII 字符都表示为\0后跟 ASCII 值的一对字节。

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.

并且由于 x86 CPU 是小端的,这些字节的顺序被交换,因此 ASCII 值首先出现,然后是空字节。

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:

通常,在进行 Windows 编程时,您有三个选择:

  • Explicitly use Unicode (call wmain, and for every Windows API function which takes char-related arguments, call the -Wversion of the function. Instead of CreateWindow, call CreateWindowW). And instead of using charuse wchar_t, and so on
  • Explicitly disable Unicode. Call main, and CreateWindowA, and use charfor strings.
  • Allow both. (call _tmain, and CreateWindow, which resolve to main/_tmain and CreateWindowA/CreateWindowW), and use TCHAR instead of char/wchar_t.
  • 显式使用 Unicode(调用 wmain,对于每个接受字符相关参数的 Windows API 函数,调用-W函数的版本。而不是 CreateWindow,调用 CreateWindowW)。而不是使用charuse wchar_t,等等
  • 显式禁用 Unicode。调用 main 和 CreateWindowA,并char用于字符串。
  • 两者都允许。(调用 _tmain 和 CreateWindow,它们解析为 main/_tmain 和 CreateWindowA/CreateWindowW),并使用 TCHAR 而不是 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.

这同样适用于 windows.h 定义的字符串类型:LPCTSTR 解析为 LPCSTR 或 LPCWSTR,并且对于包含 char 或 wchar_t 的每个其他类型,始终存在可以使用的 -T- 版本。

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.

请注意,所有这些都是 Microsoft 特定的。TCHAR 不是标准的 C++ 类型,它是 windows.h 中定义的宏。wmain 和 _tmain 也仅由 Microsoft 定义。

回答by Michael J

_tmain is a macro that gets redefined depending on whether or not you compile with Unicode or ASCII. It is a Microsoft extension and isn't guaranteed to work on any other compilers.

_tmain 是一个重新定义的宏,具体取决于您是使用 Unicode 还是 ASCII 进行编译。它是 Microsoft 的扩展,不保证适用于任何其他编译器。

The correct declaration is

正确的声明是

 int _tmain(int argc, _TCHAR *argv[]) 

If the macro UNICODE is defined, that expands to

如果定义了宏 UNICODE,则扩展为

int wmain(int argc, wchar_t *argv[])

Otherwise it expands to

否则它扩展为

int main(int argc, char *argv[])

Your definition goes for a bit of each, and (if you have UNICODE defined) will expand to

您的定义适用于每个,并且(如果您定义了 UNICODE)将扩展为

 int wmain(int argc, char *argv[])

which is just plain wrong.

这是完全错误的。

std::cout works with ASCII characters. You need std::wcout if you are using wide characters.

std::cout 适用于 ASCII 字符。如果您使用宽字符,则需要 std::wcout。

try something like this

尝试这样的事情

#include <iostream>
#include <tchar.h>

#if defined(UNICODE)
    #define _tcout std::wcout
#else
    #define _tcout std::cout
#endif

int _tmain(int argc, _TCHAR *argv[]) 
{
   _tcout << _T("There are ") << argc << _T(" arguments:") << std::endl;

   // Loop through each argument and print its number and value
   for (int i=0; i<argc; i++)
      _tcout << i << _T(" ") << argv[i] << std::endl;

   return 0;
}

Or you could just decide in advance whether to use wide or narrow characters. :-)

或者您可以提前决定是使用宽字符还是窄字符。:-)

Updated 12 Nov 2013:

2013 年 11 月 12 日更新:

Changed the traditional "TCHAR" to "_TCHAR" which seems to be the latest fashion. Both work fine.

将传统的“TCHAR”改为“_TCHAR”,似乎是最新的时尚。两者都工作正常。

End Update

结束更新

回答by Paul Alexander

the _T convention is used to indicate the program should use the character set defined for the application (Unicode, ASCII, MBCS, etc.). You can surround your strings with _T( ) to have them stored in the correct format.

_T 约定用于指示程序应使用为应用程序定义的字符集(Unicode、ASCII、MBCS 等)。你可以用 _T( ) 包围你的字符串,让它们以正确的格式存储。

 cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl;

回答by CashCow

Ok, the question seems to have been answered fairly well, the UNICODE overload should take a wide character array as its second parameter. So if the command line parameter is "Hello"that would probably end up as "H\0e\0l\0l\0o\0\0\0"and your program would only print the 'H'before it sees what it thinks is a null terminator.

好的,这个问题似乎已经得到了很好的回答,UNICODE 重载应该将宽字符数组作为其第二个参数。因此,如果命令行参数"Hello"可能会以 as 结束,"H\0e\0l\0l\0o\0\0\0"并且您的程序只会'H'在它看到它认为是空终止符之前打印。

So now you may wonder why it even compiles and links.

所以现在你可能想知道为什么它甚至编译和链接。

Well it compiles because you are allowed to define an overload to a function.

好吧,它可以编译,因为您可以定义函数的重载。

Linking is a slightly more complex issue. In C, there is no decorated symbol information so it just finds a function called main. The argc and argv are probably always there as call-stack parameters just in case even if your function is defined with that signature, even if your function happens to ignore them.

链接是一个稍微复杂的问题。在 C 中,没有装饰符号信息,所以它只找到一个名为 main 的函数。argc 和 argv 可能总是作为调用堆栈参数存在,以防万一,即使您的函数是用该签名定义的,即使您的函数碰巧忽略了它们。

Even though C++ does have decorated symbols, it almost certainly uses C-linkage for main, rather than a clever linker that looks for each one in turn. So it found your wmain and put the parameters onto the call-stack in case it is the int wmain(int, wchar_t*[])version.

尽管 C++ 确实有装饰符号,但它几乎肯定使用 C 链接作为 main,而不是一个聪明的链接器,它依次查找每个符号。所以它找到了你的 wmain 并将参数放入调用堆栈,以防它是int wmain(int, wchar_t*[])版本。

回答by Misgevolution

With a little effort of templatizing this, it wold work with any list of objects.

稍微做一些模板化工作,它就可以处理任何对象列表。

#include <iostream>
#include <string>
#include <vector>

char non_repeating_char(std::string str){
    while(str.size() >= 2){
        std::vector<size_t> rmlist; 
        for(size_t  i = 1;  i < str.size(); i++){        
            if(str[0] == str[i]) {
                rmlist.push_back(i);
            }      
        }          

        if(rmlist.size()){            
            size_t s = 0;  // Need for terator position adjustment   
            str.erase(str.begin() + 0);
            ++s;
            for (size_t j : rmlist){   
                str.erase(str.begin() + (j-s));                
                ++s;
            }
         continue;
        }
        return str[0];
   }
    if(str.size() == 1) return str[0];
    else return -1;
}

int main(int argc, char ** args)
{
    std::string test = "FabaccdbefafFG";
    test = args[1];
    char non_repeating = non_repeating_char(test);
    Std::cout << non_repeating << '\n';
}