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

why does wcslen count 1 extra character on argv[1]?

本文关键字:1个 计算 字符 wcslen argv 为什么      更新时间:2023-10-16

argv[1]似乎比输入多返回1个字符。argv[2]是正确的

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

我使用mingw32来编译。我用gcc myprog.c编译。

为什么会这样?

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

但是,大多数编译器对main参数的类型安全是宽松的。它很高兴地允许您声明main接受argc和argv的任何类型的参数(或不接受参数)。我认为这在很大程度上与C的向后兼容性有关。由于将char*[]类型隐式地强制转换为wchar_t*[],字符串将以完全不同的方式进行解释。

所以说你从预期的wcslen中得到的+1是不正确的。这在技术上是未定义的行为。

两个可能的修复:

简单的修复方法就是将第二个参数改为char字符串数组,而不是wchar_t字符串数组。

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

如果你的编译器是Visual Studio,并且你想要传递Unicode参数,修复方法是将程序的入口点声明为wmain而不是main

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

上面的wmain修复当然可以用mingw编译,但我不确定链接器是否支持启用wmain作为程序入口点。

以下是C标准草案n1570.pdf:

5.1.2.2.1程序启动

1程序启动时调用的函数命名为main。实现没有为这个函数声明原型。它的返回类型为int,不带形参:

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

或带两个形参(此处称为argc和argv,但可以使用任何名称,因为它们对于声明它们的函数来说是局部的):

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

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

因此,int可以用定义为int的类型定义名来替换,或者argv的类型可以写成char ** argv,以此类推。

这应该很容易理解。如果您的实现以wchar_t**类型支持argv,那么它将以实现定义的方式在您的实现上工作。如果你需要可移植性,不要依赖任何实现定义的东西。

此外,wcslen()被声明为返回size_t的值,您应该使用%zu指令来打印该值,并且#include <wchar.h>可能也是一个好主意。

我不认为这两个都导致了你的问题,但它们都导致了未定义的行为。