提问人:Nan Xiao 提问时间:11/16/2023 更新时间:11/16/2023 访问量:65
为什么 clang 和 gcc 在“-std=c89”选项下输出不同的结果?
Why clang and gcc output different results under `-std=c89` option?
问:
我遇到了这个测验,所以想自己验证一下:
#include <stdio.h>
void
print_sum(a, b)
{
printf("%d\n", a + b);
}
int
main(void)
{
print_sum(1.5, 8.5);
return 0;
}
我用 https://godbolt.org/ 来测试一下:
(1)与选项一起使用,结果是;
(2)但是对于选项,结果是 。
根据我的理解,and的默认类型应该是,所以在传递给时应该转换为和转换为。但显然没有遵循它。x86-64 clang (trunk)
-std=c89
9
x86-64 gcc (trunk)
-std=c89
158013177
a
b
int
1.5
1
8.5
8
print_sum()
gcc
所以我只是想知道,这是一个错误还是上面的程序有“未定义的行为?c89
gcc
答:
3赞
Keith Thompson
11/16/2023
#1
程序具有未定义的行为。
这:
void
print_sum(a, b)
是一个“老式”的宣言。它 make 和 参数类型,但它不会将该信息传达给任何调用者。a
b
int
此调用:
print_sum(1.5, 8.5);
由于可见声明不是函数的原型,因此会导致编译器假定被调用的函数采用两个类型的参数。参数不会从 转换为 。它们只是作为 传递,并且该函数假定它已被赋予两个参数。不同的行为可能是由于不同的调用约定(不太可能,因为 gcc 和 clang 应该兼容)或不同的优化。double
double
int
double
int
解决方法是将声明更改为原型,即指定其参数类型的声明。更改此设置:
void
print_sum(a, b)
对此:
void
print_sum(int a, int b)
评论
0赞
emacs drives me nuts
11/17/2023
如果可见声明不是函数的原型,那么为什么会起作用呢?void print_sum(int a, int b) {... }
0赞
Keith Thompson
11/17/2023
@emacsdrivesmenuts 这是一个原型。我没有说可见声明不是原型,我说过那个特定的可见声明()不是原型。void print_sum(a, b)
0赞
emacs drives me nuts
11/17/2023
但仍然收到警告。-Wmissing-prototypes
0赞
Keith Thompson
11/17/2023
@emacsdrivesmenuts警告一些有效代码:“如果在没有先前原型声明的情况下定义全局函数,则发出警告。 提供原型和定义,这是有效的。该警告虽然不是必需的,但是一个合理的警告。请注意,它仅适用于全局函数。gcc -Wmissing-prototypes
void print_sum(int a, int b) { printf("%d\n", a + b); }
0赞
Keith Thompson
11/17/2023
如果定义为(因此其名称仅在该源文件中可见),则不会出现警告。如果它是全局的,那么它应该在文件中有一个声明,在相应的文件中有一个单独的定义。在玩具示例中,警告意义不大,例如问题中的代码(尽管我仍然将函数定义为,除非它们实际上需要全局)。print_sum
static
.h
.c
static
评论