以下代码在gcc
上使用clang
和Linux x64
进行编译时不会发出任何警告:
#include <stdio.h>
#include <stdlib.h>
void foo(void);
void foo(void);
void foo(void);
int main(void)
{
return 0;
}
IMO,根据C99的以下片段是合法的:
引用同一对象或函数的所有声明都应具有 兼容型;否则,行为未定义。
(...)
两个功能 要兼容的类型,都应指定兼容的返回类型
(...)
此外,参数类型列表,如果两者都存在,则应同意 参数的数量和省略号终止符的使用;相应 参数应具有兼容的类型。
(...)
如果类型相同,则两种类型具有兼容类型。
我是对的吗?我想确保它不是UB并且我的理解是正确的。
答案 0 :(得分:4)
多个相同的原型是合法的,并且实际上是常见的,因为在现代C中,函数定义通常包含该函数的原型,并且还包含一个原型,用于包含a头文件。也就是说,给定
<强> foo.h中强>:
void foo(int x);
<强> foo.c的强>:
#include "foo.h"
void foo(int x) {
printf("%d\n", x);
}
/* ... */
在函数foo()
的定义范围内以及整个文件的其余部分中,foo
有两个相同的原型。这很好。
只要它们兼容,就可以对同一个对象或函数的多个声明进行相同。例如, 声明
void foo();
将foo
声明为一个接受未指定参数并且不返回任何内容的函数。此声明与foo.c
和foo.h
中已存在的声明兼容,并且可以将其添加到其中一个或两个文件中,但不会产生额外影响。
这一切都适用于对象(变量),其中一些应用程序很常见。例如,如果要声明从多个文件访问的全局变量,则通常将该变量的声明放在头文件中。包含C变量的源文件和该变量的定义 - 也是一个声明 - 通常是#include
标题,产生两个声明:
<强> global.h 强>:
extern int global;
<强> global.c 强>:
#include "global.h"
int global = 42;
或者存在复合数据类型的前向声明的情况:
struct one;
struct two {
struct one *my_one;
struct two *next;
};
struct one {
struct two *my_two;
}
请注意struct one
的多个兼容但不相同的声明。如果没有多个声明其中一种类型,则无法声明这组特定的数据结构。