你的 C 语言并非标准 C
your C is not standard C
标准 C 语言在现实中往往名存实亡。GCC 和 Clang 默认将 asm 视为关键字而非标识符,FLT_ROUNDS 宏在 GCC 中无法动态反映运行时舍入模式,标准 pragma 指令在主流编译器中大多失效。此外,glibc 的 initstate 函数错误处理不符合 POSIX 规范,Clang 对函数返回类型限定符的处理也与标准相悖,而 musl 库中的 va_start 定义甚至阻碍了 C23 新特性的使用。这些广泛存在的非标准行为,让遵循标准的代码在实际编译中频频碰壁。
委员会创造了一种无人能够或愿意实际使用的虚幻语言。
HN 评论区
19- 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
- dzaima
> 然而,gcc 始终将 FLT_ROUNDS 定义为 1
嗯,考虑到 gcc 并不支持 FENV_ACCESS pragma,因此所有的 fesetround 调用本质上都是未定义行为(UB),那么 gcc 表现得好像舍入模式从未从默认值改变过,这在逻辑上是完全成立的。
- MisterTea
作为一个热爱并享受编写 Plan 9 C 的人,我只能说所谓的“标准 C”,不管它现在意味着什么,简直是一团糟。问题多到数不过来:仅有的两个开源编译器已经臃肿不堪,C99 之后的新增功能毫无意义,内联汇编破坏了可移植性*,而 POSIX 最好直接进火葬场(顺便把打字机终端也一起烧了)。
我有个朋友目前在 C 标准委员会工作,他很可能会因为那些已经被采纳以及即将被采纳的糟糕想法而离职。
* 不,在源文件中到处塞满一百万个丑陋的 #ifdef 既恶心又难以阅读。把代码拆分好,拜托了。