如果我使用以下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;
}
我得到了我的期望,我的论点被打印出来。
但是,如果我使用_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;
}
它只显示每个参数的第一个字符。
造成这种情况的区别是什么?
答案 0 :(得分:343)
_tmain
。 main
确实如此。
_tmain
是Microsoft扩展程序。
main
是程序的切入点。
它有以下两个签名之一:
int main();
int main(int argc, char* argv[]);
Microsoft已添加一个wmain,用以下内容替换第二个签名:
int wmain(int argc, wchar_t* argv[]);
然后,为了更容易在Unicode(UTF-16)和它们的多字节字符集之间切换,他们定义了_tmain
,如果启用了Unicode,则编译为wmain
,以及main
。
至于你问题的第二部分,谜题的第一部分是你的主要功能是错误的。 wmain
应该采用wchar_t
参数,而不是char
。由于编译器没有为main
函数强制执行此操作,因此您将获得一个程序,其中wchar_t
个字符串数组被传递给main
函数,该函数将它们解释为char
} strings。
现在,在UTF-16中,启用Unicode时Windows使用的字符集,所有ASCII字符都表示为字节对\0
,后跟ASCII值。
由于x86 CPU是little-endian,所以这些字节的顺序是交换的,因此ASCII值首先出现,然后是空字节。
在char字符串中,字符串通常如何终止?是的,由空字节组成。所以你的程序会看到一串字符串,每个字节长一个。
通常,在进行Windows编程时有三个选项:
-W
版本。而不是CreateWindow,调用CreateWindowW)。而不是使用char
使用wchar_t
,等等char
作为字符串。同样适用于windows.h定义的字符串类型: LPCTSTR解析为LPCSTR或LPCWSTR,对于包含char或wchar_t的每个其他类型,始终存在-T-版本,可以替代使用。
请注意,所有这些都是Microsoft特定的。 TCHAR不是标准的C ++类型,它是在windows.h中定义的宏。 wmain和_tmain也仅由Microsoft定义。
答案 1 :(得分:34)
_tmain是一个根据您是否使用Unicode或ASCII编译而重新定义的宏。它是Microsoft扩展,不保证可以在任何其他编译器上工作。
正确的声明是
int _tmain(int argc, _TCHAR *argv[])
如果定义了宏UNICODE,则扩展为
int wmain(int argc, wchar_t *argv[])
否则它会扩展为
int main(int argc, char *argv[])
你的定义各有一点,并且(如果你定义了UNICODE)将扩展到
int wmain(int argc, char *argv[])
这是完全错误的。
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;
}
或者您可以提前决定是使用宽字符还是窄字符。 : - )
2013年11月12日更新:
将传统的“TCHAR”改为“_TCHAR”,这似乎是最新的时尚。两者都很好。
结束更新
答案 2 :(得分:9)
_T约定用于指示程序应使用为应用程序定义的字符集(Unicode,ASCII,MBCS等)。您可以使用_T()包围字符串,以便以正确的格式存储它们。
cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl;
答案 3 :(得分: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*[])
版本。
答案 4 :(得分:-1)
稍微努力将其模板化,就可以使用任何对象列表。
class TestFollowing < ActiveRecord::Migration
def change
create_table :following do |t|
t.integer :user_id, index: true
t.integer :folowed_user_id, index: true
end
end
end