【问题标题】:printf and wprintf in single C code单个 C 代码中的 printf 和 wprintf
【发布时间】:2012-01-30 16:24:45
【问题描述】:

在代码中同时使用 printfwprintf 函数时遇到问题。如果先打印常规字符串,则 wprintf 不起作用。如果我先使用wprintf,那么printf 将不起作用。

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>

int main() 
{
    setlocale(LC_ALL,"");

    printf("No printing!\n");
    wprintf(L"Printing!\n");
    wprintf(L"Wide char\n");
    printf("ASCII\n");
    return 0;
}

输出:

No printing!
ASCII

虽然

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>

int main() 
{
    setlocale(LC_ALL,"");

    wprintf(L"Printing!\n");
    printf("No printing!\n");
    wprintf(L"Wide char\n");
    printf("ASCII\n");
    return 0;
}

输出:

Printing!
Wide char

我在 64 位 Linux 3.0 上使用 gcc (GCC) 4.6.1 20110819 和 glibc 2.14。

【问题讨论】:

  • Linux 3.0?那是什么?什么分布?
  • @bmargulies:内核版本。发行版是 Archlinux。

标签: c gcc internationalization


【解决方案1】:

这是意料之中的;您的代码正在调用未定义的行为。根据 C 标准,每个FILE 流都与一个“方向”(“字节”或“宽”)相关联,该方向由对其执行的第一个操作设置,并且可以使用fwide 函数进行检查。调用方向与流方向冲突的任何函数都会导致未定义的行为。

【讨论】:

  • 如果方向与要写入的数据不匹配,是未定义的行为还是什么都不输出?
  • @alk 未定义的行为意味着在这种情况下它的行为方式没有预期。因此,什么都不输出是可以接受的,就像默默地将文本转换为正确的方向或打印垃圾一样。
  • @Hubert:这不是手册页中的错误。 kernel.org/doc/man-pages/online/pages/man3/wprintf.3.html 说:“stdout 不能面向字节”
  • 是否可以重新打开stdout并更改方向?
  • freopen 可以清除方向,但也有缺点。有关此事,请参阅 POSIX:pubs.opengroup.org/onlinepubs/9699919799/functions/freopen.html 特别是“应用程序使用”部分。
【解决方案2】:

补充 R.. 接受的答案:

虽然很少这样做,但检查 printf/wprintf 的返回码会更清楚地表明其中一个不工作(它应该返回 -1 表示根据当前无效的打印功能流的方向)。

不幸的是,在标准库函数中检查错误的常见模式:

if (wprintf(...) == -1) { perror("wprintf"); ... }

在这里可能没有多大帮助:如果流设置为输出非宽字符,并且您调用wprintf,则可能未设置errno,您将获得wprintf: Success,它没有提供太多信息.

因此,当您不了解流的字符方向时,这确实是一个有点难以理解的问题。

【讨论】:

  • 检查返回值有助于当您有可报告的错误时,而不是当您有未定义的行为时。 wprintf 未指定在方向错误时失败。相反,当方向错误时它的作用是根本没有指定。这就是未定义的意思。
猜你喜欢
  • 2015-01-05
  • 2019-07-01
  • 2011-02-12
  • 2012-04-12
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 2013-03-27
相关资源
最近更新 更多