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

jos*_*ley 222 c++ unicode arguments

如果我使用以下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;
}
Run Code Online (Sandbox Code Playgroud)

我得到了我的期望,我的论点被打印出来了.

但是,如果我使用_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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

jal*_*alf 352

_tmain在C++中不存在.main确实.

_tmain 是Microsoft扩展.

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

int main();
int main(int argc, char* argv[]);
Run Code Online (Sandbox Code Playgroud)

Microsoft已添加一个wmain,用以下内容替换第二个签名:

int wmain(int argc, wchar_t* argv[]);
Run Code Online (Sandbox Code Playgroud)

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

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

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

并且由于x86 CPU是little-endian,所以这些字节的顺序是交换的,因此ASCII值首先出现,然后是空字节.

在char字符串中,字符串通常如何终止?是的,由空字节组成.所以你的程序会看到一串字符串,每个字节长一个字节.

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

  • 显式使用Unicode(调用wmain,对于每个采用与char相关的参数的Windows API函数,调用-W函数的版本.而不是CreateWindow,调用CreateWindowW).而不是char使用wchar_t,等等
  • 显式禁用Unicode.调用main和CreateWindowA,并char用于字符串.
  • 允许两者.(调用_tmain和CreateWindow,它们解析为main/_tmain和CreateWindowA/CreateWindowW),并使用TCHAR而不是char/wchar_t.

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

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

  • 为什么你认为这更实际? (10认同)
  • 我想知道他们是否也提供了一个tcout?所以人们可以做tcout << argv [n]; 它解析为Ansi中的cout和Unicode模式下的wcout?我怀疑在这种情况下对他有用.和+1当然,很好的答案:) (6认同)
  • -1列出的三个选项均不可行。Windows编程的实际方法是定义UNICODE。以及在添加&lt;windows.h&gt;之前对C ++等进行的其他一些调整。然后使用Unicode函数,例如“ CreateWindow”(通常不需要结尾的“ W”)。 (2认同)

Mic*_*l J 35

_tmain是一个根据您是否使用Unicode或ASCII编译而重新定义的宏.它是Microsoft扩展,不保证可以在任何其他编译器上工作.

正确的声明是

 int _tmain(int argc, _TCHAR *argv[]) 
Run Code Online (Sandbox Code Playgroud)

如果定义宏UNICODE,则扩展为

int wmain(int argc, wchar_t *argv[])
Run Code Online (Sandbox Code Playgroud)

否则它会扩展到

int main(int argc, char *argv[])
Run Code Online (Sandbox Code Playgroud)

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

 int wmain(int argc, char *argv[])
Run Code Online (Sandbox Code Playgroud)

这是完全错误的.

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

尝试这样的事情

#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;
}
Run Code Online (Sandbox Code Playgroud)

或者您可以事先决定是使用宽字符还是窄字符.:-)

2013年11月12日更新:

将传统的"TCHAR"改为"_TCHAR",这似乎是最新的时尚.两者都很好.

结束更新

  • 这是这个四年前的答案最近第二次被否决。如果投反对票的人发表评论解释他们认为存在哪些问题以及(如果可能的话)如何改进答案,那就太好了。b1naryatr0phy 发现一个写得不好的句子,但我在三月份修复了它。任何指导将不胜感激。 (2认同)
  • 生命太短暂了。 (2认同)

Pau*_*der 9

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

 cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl;
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一下,如果你尝试在UNICODE上编译,那么你的代码将不会编译为在基于char的cout中输出wchar_t,它应该是wcout.有关定义"tcout"的例子,请参阅Michael J的答案...... (5认同)

Cas*_*Cow 5

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

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

好吧它编译因为你被允许定义一个函数的重载.

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

即使C++确实有装饰符号,它几乎肯定会使用C-linkage作为main,而不是依次查找每个符号的聪明链接器.所以它找到了你的wmain并将参数放在call-stack上,以防它是int wmain(int, wchar_t*[])版本.