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

我试过以下代码:

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 

我得到以下输出:

 1 some string 2 s 3 some string 1 g1 %s 2 some string 4 some string 

所以:似乎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 

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

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

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

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

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

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

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

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

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

%S似乎符合单一Unix规范v2 ,也是当前(2008) POSIX规范的一部分 。

符合C99标准的等效格式说明符为%s%ls