有哪些非ISO规范的示例未被-pedantic找到?

9
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html : 一些用户尝试使用-Wpedantic来检查程序是否符合严格的ISO C标准。他们很快发现它并不完全满足他们的要求:它可以找到一些非ISO惯例,但不是全部,只有那些ISO C 需要进行诊断的情况以及添加了一些其他的诊断。具体哪些非ISO惯例无法通过-pedantic找到呢?
3个回答

4
这里的根本问题在于编写包含错误(不仅是未能达到严格一致性要求的失败)的C程序是可能的,但要求C编译器检测这些错误是不合理的。在标准最初编写的时候(1989年),整个程序分析是不可能的,即使现在,它也很昂贵。而且人们始终可以创造出像下面这样的结构:
extern _Bool collatz_sequence_does_not_terminate(int);
int foo(int n) {
    int rv;
    if (collatz_sequence_does_not_terminate(n)) {
        return rv;
    }
    return 23;
}

当涉及到一个数学问题的解未知时,“这个程序是否有未定义行为”这个问题的答案就会不确定。

因此,该手册试图警告您,不仅是GCC无法检测 ISO C 符合性的所有可能违规行为,而且没有任何编译器可以做到。如果我还在从事GCC工作,我可能会修改一下措辞,使它更清晰。


如果你想要一个具体的例子,即使不符合标准,但不会被诊断出来,并且在现实生活中相对容易出现,请试试以下示例:

/* a.c */
#include <stdint.h>
uint64_t val = 0x0123456789abcdef;

/* b.c */
#include <stdio.h>
extern double val;
int main(void) {
    printf("%g\n", val);
    return 0;
}

需要进行整个程序的分析才能检测出两个文件之间的类型不匹配。这并不是一个困难的情况;编译器可以用其类型注释每个全局符号,链接器可以检查每个符号的所有用法是否与定义一致。但我不知道任何工具链或静态分析产品,它们将会检测到变量的此类错误。


3
小问题反驳:对于所有的 int n 值,Collatz 序列都被证明是终止的。 :-) 因此程序是正确的。 - Jens

4

GCC支持ISO C标准未要求的其他形式的常量表达式。

int main() {
  const int m = 5;
  static int n = m;
  return n;
}

即使使用不符合ISO C常量表达式的东西来初始化static变量,这段代码在“pedantic”模式下也可以编译通过。


可能会有用:https://stackoverflow.com/a/67266324/1778275。 - pmor

1
  1. C 预处理器,11.1 实现定义行为

GCC 允许在大多数目标中使用 '$' 字符作为标识符的扩展。这是无论 std= 开关如何都成立的,因为此扩展不会与符合标准的程序冲突。然而,在预处理汇编程序时,默认情况下,美元符号不是标识符字符。

更新 2. 允许 "plain complex":

#include <complex.h>
complex x;

$ gcc t0.c -std=c11 -pedantic -Wall -Wextra
<nothing>

C11,6.2.5类型,第11条:

有三种复杂类型,被指定为 float _Complex double _Complex long double _Complex

以及7.3.1简介,第4条:

complex 扩展为 _Complex

UPD. 3. __has_attribute

#if __has_attribute(xxx)
#endif
int x;

$ gcc t0.c -std=c11 -pedantic -Wall -Wextra
<nothing>

我并不反对,但这似乎是一个奇怪的具体例子来证明重新激活这个问题的必要性。从J.1 - J.5的附录中可以引用各种各样的例子。虽然GCC会诊断其中的一些问题,但还有很多问题它无法诊断。我个人最喜欢的是“非空源文件不以未立即在其前面加上反斜杠字符的换行符结尾”。 - John Bollinger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接