我尝试过以下代码:
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
所以:似乎wprintf
和printf
都能正确打印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
答案 0 :(得分:22)
我怀疑GCC(mingw)有自定义代码来禁用对Windows上的宽printf
函数的检查。这是因为Microsoft自己的实现(MSVCRT)严重错误并且%s
和%ls
向后用于广printf
个函数;由于海湾合作委员会无法确定你是否会与MS的破坏实施或一些纠正的实施相关联,所以它能做的最不突兀的事情就是关闭警告。
答案 1 :(得分:17)
格式说明符很重要:“%s”表示下一个字符串是一个窄字符串(“ascii”,通常每个字符8位)。 “%S”表示宽字符串。混合两者将产生“未定义的行为”,其中包括打印垃圾,只有一个字符或什么都没有。
打印一个字符,因为宽字符例如是16位宽,第一个字节是非零,后跟零字节 - >窄字符串中的字符串结尾。这取决于字节顺序,在“大端”机器中,你根本就没有字符串,因为第一个字节是零,下一个字节包含一个非零值。
答案 2 :(得分:4)
至少在Visual C ++中: printf(和其他ACSII函数): %s表示ASCII字符串 %S是Unicode字符串 wprintf(和其他Unicode函数): %s是一个Unicode字符串 %S是ASCII字符串
就没有编译器警告而言,printf使用可变参数列表,只能对第一个参数进行类型检查。编译器不是为解析格式字符串而设计的,而是检查匹配的参数。在像printf这样的函数的情况下,这取决于程序员
答案 3 :(得分:3)
对于s: 与printf函数一起使用时,指定单字节或多字节字符串;与wprintf函数一起使用时,指定宽字符串。字符显示到第一个空字符或直到达到精度值。
对于S: 与printf函数一起使用时,指定宽字符串;与wprintf函数一起使用时,指定单字节或多字节字符串。字符显示到第一个空字符或直到达到精度值。
在类Unix平台中,s和S与windows平台具有相同的含义。
答案 4 :(得分:0)
%S
似乎符合The Single Unix Specification v2,也是当前(2008)POSIX specification的一部分。
符合C99标准的格式说明符为%s
和%ls
。
答案 5 :(得分:0)
以上所有答案均未指出为什么您看不到某些印刷品。这也是因为在这里您正在处理流(我不知道),并且流具有称为方向的东西。让我从this来源中引用一些内容:
窄而宽的方向
新打开的视频流没有方向。首次调用任何I / O功能 确定方向。
广泛的I / O功能使流 面向,狭窄的I / O功能使流面向。 设置后,只能使用freopen更改方向。
窄I / O 不能在面向广泛的流上调用函数;宽I / O 不能在狭窄的流上调用函数。宽I / O 函数在宽字符和多字节字符之间进行转换,就像通过 呼叫mbrtowc和wcrtomb。与多字节字符串不同 在程序中有效的文件中的多字节字符序列 可能包含嵌入的null,而不必以 初始换档状态。
因此,一旦您使用printf()
,您的方向就会变得狭窄,从这一点开始,您将无法从wprintf()
中获得任何东西,而您确实没有。除非您使用旨在用于文件的freeopen()
。
事实证明,您可以像这样使用freeopen()
:
freopen(NULL, "w", stdout);
再次使流“未定义” 。试试这个例子:
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(void)
{
// We set locale which is the same as the enviromental variable "LANG=en_US.UTF-8".
setlocale(LC_ALL, "en_US.UTF-8");
// We define array of wide characters. We indicate this on both sides of equal sign
// with "wchar_t" on the left and "L" on the right.
wchar_t y[100] = L"?€ο Δικαιοπολις εν αγρω εστιν\n";
// We print header in ASCII characters
wprintf(L"content-type:text/html; charset:utf-8\n\n");
// A newly opened stream has no orientation. The first call to any I/O function
// establishes the orientation: a wide I/O function makes the stream wide-oriented,
// a narrow I/O function makes the stream narrow-oriented. Once set, we must respect
// this, so for the time being we are stuck with either printf() or wprintf().
wprintf(L"%S\n", y); // Conversion specifier %S is not standardized (!)
wprintf(L"%ls\n", y); // Conversion specifier %s with length modifier %l is
// standardized (!)
// At this point curent orientation of the stream is wide and this is why folowing
// narrow function won't print anything! Whether we should use wprintf() or printf()
// is primarily a question of how we want output to be encoded.
printf("1\n"); // Print narrow string of characters with a narrow function
printf("%s\n", "2"); // Print narrow string of characters with a narrow function
printf("%ls\n",L"3"); // Print wide string of characters with a narrow function
// Now we reset the stream to no orientation.
freopen(NULL, "w", stdout);
printf("4\n"); // Print narrow string of characters with a narrow function
printf("%s\n", "5"); // Print narrow string of characters with a narrow function
printf("%ls\n",L"6"); // Print wide string of characters with a narrow function
return 0;
}