gcc在c99模式下是否错误地执行隐式函数声明?

gcc在c99模式下是否错误地执行隐式函数声明?,gcc,standards,c99,c89,Gcc,Standards,C99,C89,考虑以下代码: int main (void) { int i = xyzzy(); return i; } int xyzzy (void) { return 42; } 现在,虽然xyzy的原型在使用时是未知的,但它在c89模式下工作,因为没有原型的函数的默认返回类型是int,因此隐式函数原型和实际函数是兼容的 事实上,如果您将函数的返回类型更改为float,您将得到(如预期的那样): 因为隐式原型和实际函数不再匹配 用gcc--std=c89--pedantic-

考虑以下代码:

int main (void) {
    int i = xyzzy();
    return i;
}
int xyzzy (void) {
    return 42;
}
现在,虽然
xyzy
的原型在使用时是未知的,但它在c89模式下工作,因为没有原型的函数的默认返回类型是
int
,因此隐式函数原型和实际函数是兼容的

事实上,如果您将函数的返回类型更改为
float
,您将得到(如预期的那样):

因为隐式原型和实际函数不再匹配

用gcc--std=c89--pedantic-Wall-Wextra编译的原始代码只给了我一个警告:

testprog.c: In function 'main':
testprog.c:2: warning: implicit declaration of function 'xyzzy'
这是预期的,因为c89在
3.7.1函数定义中有这样的表述:

extern int max(int a,int b){…}:这里
extern
是存储类说明符,
int
是类型说明符(每个都可以省略,因为它们是默认值)

3.3.2.2函数调用中

如果函数调用中括号参数列表前面的表达式仅由标识符组成,并且如果该标识符没有可见的声明,则该标识符将被隐式声明,就像在包含 函数调用,声明extern int identifier()出现了

因此,在声明函数之前使用它肯定会导致创建默认原型


但是,c99中删除了这两个短语,我们在
6.5.2.2函数调用中找到了它们(我的粗体):

如果表示被调用函数的表达式具有指向返回对象类型的函数的类型指针,则函数调用表达式具有与该对象类型相同的类型,并且具有6.8.6.4中规定的值否则,函数调用的类型为void。

我理解它的意思是,如果在您尝试调用函数时,视图中没有声明,那么它将使用
void
返回类型隐式声明

然而,当使用
gcc--std=c99--pedantic-Wall-Wextra
编译时,我得到了与隐式声明相同的警告

c99不应该隐式声明该函数返回
void
?如果有,我会预料到一个
以前的隐式声明
错误,类似于我在尝试将其重新声明为返回
float
时遇到的错误


这里是否有
gcc
错误,或者我在标准中遗漏了什么?

您阅读的标准不正确。C语言中没有隐式函数声明。C99将其从语言中删除


GCC在看到类似于隐式函数声明的错误构造时发出警告。就标准而言,这是可以的。本标准要求在此进行诊断,警告即为诊断。您可以使用GCC的
-Werror=implicit function declaration
标志将其转化为错误。

这将在6.5.1主要表达式的注释中介绍:

2-标识符是主表达式,前提是它已声明为指定 对象(在这种情况下是左值)或函数(在这种情况下是函数 指示符)。(79)


79)因此,未声明的标识符违反了语法

5.1.1.3 Diagnostics要求一致性实现,以生成诊断消息,响应函数调用表达式的语法冲突,该函数调用表达式涉及未声明的标识符,作为表示被调用函数的表达式。当然,可以自由地继续编译程序,就好像标识符是以隐式-
int
C89样式声明的一样

段落6.5.2.2p5必须参考约束6.5.2.2p1:

1-表示被调用函数的表达式应具有指向函数的类型指针 返回
void
或返回数组类型以外的对象类型

因此,如果“表示被调用函数的表达式”没有类型“指向返回对象类型的函数的指针”,则它必须事实上(根据约束6.5.2.2p1)具有类型“指向返回的函数的指针
void
”,而6.5.2.2p5中的“否则”就涵盖了这种情况。也就是说,在[方括号]中插入:

5-如果表示被调用函数的表达式具有指向返回对象类型的函数的类型指针,则函数调用表达式具有与该对象类型相同的类型,并且具有6.8.6.4中规定的值否则,[即,如果表示被调用函数的表达式具有指向返回函数的类型指针
void
,]则函数调用具有类型
void


与对象类型相反,
void
需要特殊语言;不是被调用函数表达式成为或包含未声明标识符的许可证。

sun/oracle cc编译器,带-xc99选项,并对func使用float给出当前:function(void)返回float;上一个:返回int的函数():“pax.c”,第2行;我认为很难有两个不同的编译器表现出相同的对标准的误解,即使这不是不可能的-标准应该避免使用一种使事情难以理解的语言@Shin,这使它看起来像Sun编译器即使在C99模式下也默认为“return int”,在这种情况下,可能是我读错了标准。我只是不知道在哪里。你读的不可能是正确的;它不会向后兼容。在C99中,应该有函数的声明(最好是原型声明)或函数定义,在作用域中可见。范围中的任何声明都不需要诊断(和c
testprog.c: In function 'main':
testprog.c:2: warning: implicit declaration of function 'xyzzy'