为什么wcslen在argv上计算1个额外的字符[1]?

时间:2013-01-19 02:37:41

标签: c++ c gcc mingw32 widechar

argv[1]似乎返回1个额外的字符而不是输入。 argv[2]是正确的。

#include <stdio.h>
int main(int argc, wchar_t *argv[])
{
  printf("%d %d\n",wcslen(argv[1]),wcslen(argv[2]) );
  return 0;
}

我正在使用mingw32进行编译。我用gcc myprog.c编译。

为什么会这样?

3 个答案:

答案 0 :(得分:1)

以下是C标准草案的引用,n1570.pdf:

5.1.2.2.1程序启动

1 程序启动时调用的函数名为main。该实现声明此函数没有原型。它应该用返回类型int定义,没有参数:

int main(void) { /* ... */ }

或者有两个参数(这里称为argc和argv,虽然可以使用任何名称,因为它们是声明它们的函数的本地名称):

int main(int argc, char *argv[]) { /* ... */ }

或等效; 10)或以其他一些实现定义的方式。

10)因此,int可以被定义为int的typedef名称替换,或者argv的类型可以写为char ** argv,依此类推。

理解这一点应该相当简单。如果您的实现支持类型为wchar_t **的argv,那么它将以实现定义的方式处理您的实现。如果您需要可移植性,请不要依赖任何实现定义。

答案 1 :(得分:1)

main 需要类型为 intchar**(或等效的 char*[])的参数。还有一个可选的第三个参数,它是环境字符串数组。

但是现在的情况是,大多数编译器都对 main 的参数的类型安全感到放松。它很高兴让您声明 main 为 argc 和 argv 采用任何类型的参数(或不带参数)。我认为这在很大程度上是历史性的,与 C 的向后兼容性可以做到这一点。由于将 char*[] 类型隐式转换为 wchar_t*[],字符串会以截然不同的方式进行解释。

因此,说您从 wcslen 获得的收益超出预期是不正确的。这是技术上未定义的行为。

两个可能的修复:

简单的解决方法就是将第二个参数定义为 char 字符串数组,而不是 wchar_t 字符串。

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

如果您的编译器是 Visual Studio 并且您希望传递 Unicode 参数,则解决方法是将程序的入口点声明为 wmain 而不是 main

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

上面的 wmain 修复肯定会用 mingw 编译,但我不确定链接器是否支持启用 wmain 作为程序入口点。尝试一下,找出答案。

答案 2 :(得分:0)

对此的一个很好的参考是CommandLineToArgvW function