你的 C 语言并非标准 C

your C is not standard C

标准 C 语言在现实中往往名存实亡。GCC 和 Clang 默认将 asm 视为关键字而非标识符,FLT_ROUNDS 宏在 GCC 中无法动态反映运行时舍入模式,标准 pragma 指令在主流编译器中大多失效。此外,glibc 的 initstate 函数错误处理不符合 POSIX 规范,Clang 对函数返回类型限定符的处理也与标准相悖,而 musl 库中的 va_start 定义甚至阻碍了 C23 新特性的使用。这些广泛存在的非标准行为,让遵循标准的代码在实际编译中频频碰壁。

委员会创造了一种无人能够或愿意实际使用的虚幻语言。
  1. omoikane

    GCC 至今仍未实现标准 pragma,这让我想起了 GCC 早年那个著名的 pragma 彩蛋。这段代码出自 gcc 0.9 版本的 cccp.c:

    /*

    * #pragma 指令的行为由实现定义。

    * 本实现将其定义如下。

    */

    do_pragma ()

    {

    close (0);

    if (open ("/dev/tty", O_RDONLY) != 0)

    goto nope;

    close (1);

    if (open ("/dev/tty", O_WRONLY) != 1)

    goto nope;

    execl ("/usr/games/hack", "#pragma", 0);

    execl ("/usr/games/rogue", "#pragma", 0);

    execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);

    execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);

    nope:

    fatal ("You are in a maze of twisty compiler features, all different");

    }

    到了 gcc 1.21 版本,它已经不见了:

    #if 0

    /* 这曾是个有趣的恶作剧,但 #pragma 似乎开始变得有用起来。

    通过不识别它,我们将其原样传递给 cc1。 */

    ...

    #endif

  2. dzaima

    > 然而,gcc 始终将 FLT_ROUNDS 定义为 1

    嗯,考虑到 gcc 并不支持 FENV_ACCESS pragma,因此所有的 fesetround 调用本质上都是未定义行为(UB),那么 gcc 表现得好像舍入模式从未从默认值改变过,这在逻辑上是完全成立的。

  3. MisterTea

    作为一个热爱并享受编写 Plan 9 C 的人,我只能说所谓的“标准 C”,不管它现在意味着什么,简直是一团糟。问题多到数不过来:仅有的两个开源编译器已经臃肿不堪,C99 之后的新增功能毫无意义,内联汇编破坏了可移植性*,而 POSIX 最好直接进火葬场(顺便把打字机终端也一起烧了)。

    我有个朋友目前在 C 标准委员会工作,他很可能会因为那些已经被采纳以及即将被采纳的糟糕想法而离职。

    * 不,在源文件中到处塞满一百万个丑陋的 #ifdef 既恶心又难以阅读。把代码拆分好,拜托了。

同日更多故事

2026-10-15