printf,wprintf,%s,%S,%ls,char*和wchar*:编译器警告未公布错误?

Ant*_*nio 22 c mingw

我试过以下代码:

wprintf(L"1 %s\n","some string"); //Good
wprintf(L"2 %s\n",L"some string"); //Not good -> print only first character of the string
printf("3 %s\n","some string"); //Good
//printf("4 %s\n",L"some string"); //Doesn't compile
printf("\n");
wprintf(L"1 %S\n","some string"); //Not good -> print some funny stuff
wprintf(L"2 %S\n",L"some string"); //Good
//printf("3 %S\n","some string"); //Doesn't compile
printf("4 %S\n",L"some string");  //Good
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

1 some string
2 s
3 some string

1 g1 %s

2 some string
4 some string
Run Code Online (Sandbox Code Playgroud)

所以说:看来双方wprintfprintf能正确打印都一个char*和*WCHAR,但前提是准确的说明符使用.如果使用了错误的说明符,您可能不会收到编译错误(也没有警告!)并最终导致错误行为.你有同样的行为吗?

注意:这是在Windows下测试的,用MinGW和g ++ 4.7.2 编译(我稍后会检查gcc)

编辑:我也试过%ls(结果在评论中)

printf("\n");
wprintf(L"1 %ls\n","some string"); //Not good -> print funny stuff
wprintf(L"2 %ls\n",L"some string"); //Good
// printf("3 %ls\n","some string"); //Doesn't compile
printf("4 %ls\n",L"some string");  //Good
Run Code Online (Sandbox Code Playgroud)

R..*_*R.. 23

我怀疑GCC(mingw)有自定义代码来禁用printf对Windows上的宽功能的检查.这是因为微软自己的实现(MSVCRT)是严重错误的,并具有%s%ls 向后的广泛printf功能; 由于海湾合作委员会不能确定你是否会与MS的破坏实施或一些纠正的实施相关联,它可以做的最不突兀的事情就是关闭警告.

  • @jbu:这意味着他们支持的语言不是C语言,而是微软提出的一些随机C语言.所以,如果你说你支持C,那不仅仅是与众不同,这是错误的*. (25认同)
  • 它并没有严重错误......这就像说你所做的是错的,因为你遵循自己的规范,而不是别人的(ANSI) (3认同)
  • @R ..你可以指出一个参考声明微软自己声称完全符合ANSI C标准吗?C语言本身没有引用标准就没有任何意义. (2认同)

Mat*_*son 18

格式说明符很重要:"%s"表示下一个字符串是一个窄字符串("ascii",通常每个字符8位)."%S"表示宽字符串.混合两者将产生"未定义的行为",其中包括打印垃圾,只有一个字符或什么都没有.

打印一个字符是因为宽字符例如是16位宽,第一个字节非零,后面是零字节 - >窄字符串中字符串的结尾.这取决于字节顺序,在"大端"机器中,根本没有字符串,因为第一个字节为零,下一个字节包含非零值.


小智 5

至少在 Visual C++ 中: printf(和其他 ACSII 函数):%s 表示一个 ASCII 字符串 %S 是一个 Unicode 字符串 wprintf(和其他 Unicode 函数):%s 是一个 Unicode 字符串 %S 是一个 ASCII 字符串

就没有编译器警告而言,printf 使用可变参数列表,只有第一个参数可以进行类型检查。编译器不是设计来解析格式字符串和类型检查匹配的参数的。对于 printf 之类的函数,这取决于程序员


小智 5

对于 s: 与 printf 函数一起使用时,指定单字节或多字节字符串;与 wprintf 函数一起使用时,指定宽字符串。字符一直显示到第一个空字符或达到精度值。

对于 S: 当与 printf 函数一起使用时,指定一个宽字符串;与 wprintf 函数一起使用时,指定单字节或多字节字符串。字符一直显示到第一个空字符或达到精度值。

在类 Unix 平台中,s 和 S 与 windows 平台的含义相同。

参考:https : //msdn.microsoft.com/en-us/library/hf4y5e3w.aspx