多个相同的原型是否合法?

时间:2016-03-30 19:04:50

标签: c prototype language-lawyer declaration c99

以下代码在gcc上使用clangLinux x64进行编译时不会发出任何警告:

#include <stdio.h>
#include <stdlib.h>

void foo(void);

void foo(void);

void foo(void);

int main(void)
{
    return 0;
}

IMO,根据C99的以下片段是合法的:

  

引用同一对象或函数的所有声明都应具有   兼容型;否则,行为未定义。

     

(...)

     

两个功能   要兼容的类型,都应指定兼容的返回类型

     

(...)

     

此外,参数类型列表,如果两者都存在,则应同意   参数的数量和省略号终止符的使用;相应   参数应具有兼容的类型。

     

(...)

     

如果类型相同,则两种类型具有兼容类型。

我是对的吗?我想确保它不是UB并且我的理解是正确的。

1 个答案:

答案 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.cfoo.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的多个兼容但不相同的声明。如果没有多个声明其中一种类型,则无法声明这组特定的数据结构。