c - 违反约束是否总是导致诊断?

标签 c language-lawyer

我想知道如果我在 K&R 函数定义中省略参数声明会发生什么,所以我尝试了以下操作:

#include <stdio.h>

void f(a) 
// int a;       <--- omitting `declaration-list` causes warning in gcc, but nothing in clang
{
    printf("%d", 9);
}

int main() 
{
    f(9);
    return 0;
}

当我用 gcc 11 编译它时,诊断以警告的形式发出(即 warning: type of 'a' defaults to 'int') .但是,当我用 clang 14 编译它时,没有发出任何诊断消息。

这让我感到困惑,因为在标准中,省略 declaration-list(其中包含参数声明)是违反约束的(根据 C11 6.9.1(6) ),这需要符合标准的实现才能发出诊断(根据 C11 5.1.1.3 )。 那么,为什么clang没有发出警告呢?我是不是误解了什么?


编辑: 如果编译器可以应用标准中的某些其他条款“修复”约束违规,是否必须发布诊断?

例如,上面代码中的空声明列表一直是约束违规(since C89)。然而,在 C99 之前,该标准还有一个隐式的 int 规则(参见 C90 6.5.2 ),这将允许编译器将任何未声明的参数假定为 int 从而从 no-empty-declaration-list 约束违规中恢复过来。

那么,在这种情况下,1999 年之前符合 ANSI 标准的编译器是否仍会发出诊断?我的第一印象是它会因为约束优先于隐式 int 规则,但是 pg. Harbison 和 Steele 的 287 说(强调):

In the pre-Standard traditional form, the parameter names are listed in the declarator and the types are specified (in any order) in the declaration-list opt following the declarator. All parameters should be declared in the declaration-list, but prior to C99 omitted parameter declarations defaulted to type int.

粗体字看起来像是允许空声明列表,因为隐式 int 规则会“修复”任何 no-empty-declaration-list 约束违规。

最佳答案

如果使用 -pedantic 标志编译,clang 将生成警告。

<source>:3:8: warning: parameter 'a' was not declared, defaulting to type 'int' [-Wpedantic]
void f(a) 
       ^
1 warning generated.
ASM generation compiler returned: 0
<source>:3:8: warning: parameter 'a' was not declared, defaulting to type 'int' [-Wpedantic]
void f(a) 
       ^
1 warning generated.
Execution build compiler returned: 0
Program returned: 0
9

https://godbolt.org/z/e73M1Eq8E

关于c - 违反约束是否总是导致诊断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74663869/

相关文章:

c - 我的 C 程序在新行上打印 -39,但我不明白为什么

android - 在 NDK 中使用 fopen()、fread() 打开文件时出现致命信号 11,但 AAsset_read 工作正常

c++ - C++0x 的哪些功能肯定会保留(如果有的话)?

c++ - 嵌套在类模板中的类的前向声明是否合法?

c++ - 如何使用自定义分配器(没有 UB)提供的指向原始内存的指针?

c++ - 模板类型别名可见性编译器不一致

C函数点隐藏一些变量

c++ - 将内存使用量保持在可用量内

C-将字符串保存到数组并打印字符

c - getc() 作为宏和 C 标准库函数定义,连贯吗?