为什么我需要在外部声明这个函数。没有它也能工作
Why do I need to declare this function extern. It works without it
我是外部概念的新手。今天在工作中,我遇到了大量在头文件中声明的外部函数; foo.h。在一堆文件夹的某个地方,我发现了一个 foo.c 文件,其中包含上述函数的定义,但没有 #include foo.h
。回到家后,我决定尝试使用 extern storage class 示例。在阅读了 "C book" 之后,这就是我想出的。
这是我没想到的工作。但确实如此。
main.c
#include <stdio.h>
int data;
int main()
{
data = 6;
printf("%d\n", getData());
data = 8;
printf("%d\n", getData());
return 0;
}
externs.c
int getData()
{
extern int data;
return data;
}
bash
gcc main.c externs.c -o externs
我认为这行不通,因为该函数在技术上(或至少是冗长的)没有在 main 之前定义。这是否有效,因为 int getData()
的默认存储 class 是 extern
?如果是这样,为什么还要费心看下面的例子(类似于我在工作中看到的)?
main2.c
#include <stdio.h>
#include "externs.h"
int data;
int main()
{
data = 6;
printf("%d\n", getData());
data = 8;
printf("%d\n", getData());
return 0;
}
externs.h
#ifndef _EXTERNSH_
#define _EXTERNSH_
extern int getData();
#endif
externs.c
int getData()
{
extern int data;
return data;
}
bash
gcc main2.c externs.c -o externs
函数是隐式的 extern
。您可以通过将它们声明为 static
.
来更改此设置
你是对的,说 extern int getData();
与 int getData();
相比是多余的,但有些人认为它提高了代码清晰度。
请注意,自 C99 起,您的第一个示例格式错误。它在未声明该函数的情况下调用 getData
。在 C89 中,这执行了一个隐式的 int getData();
声明,但从 C99 开始,它被删除了。使用编译器开关 -std=c99 -pedantic
进行测试。
默认情况下,GCC 版本 4.x 或更早版本在 C89/C90 兼容模式下编译,不需要在使用前声明函数。未声明的函数被推断为具有 return 类型的 int
。默认情况下,GCC 5.x 或更高版本在 C11 兼容模式下编译,这确实需要在使用前声明函数——C99 也是如此。
鉴于编译后的代码没有任何抱怨,我们可以推断您正在使用 GCC 4.x。
即使如此,您也没有义务提供完整的原型,尽管您不这样做是愚蠢的。我通常使用以下选项编译代码:
gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Wold-style-declaration …
我怀疑那里有一些冗余,但在我开始 运行 代码之前,这些选项会遇到很多问题。
我是外部概念的新手。今天在工作中,我遇到了大量在头文件中声明的外部函数; foo.h。在一堆文件夹的某个地方,我发现了一个 foo.c 文件,其中包含上述函数的定义,但没有 #include foo.h
。回到家后,我决定尝试使用 extern storage class 示例。在阅读了 "C book" 之后,这就是我想出的。
这是我没想到的工作。但确实如此。
main.c
#include <stdio.h>
int data;
int main()
{
data = 6;
printf("%d\n", getData());
data = 8;
printf("%d\n", getData());
return 0;
}
externs.c
int getData()
{
extern int data;
return data;
}
bash
gcc main.c externs.c -o externs
我认为这行不通,因为该函数在技术上(或至少是冗长的)没有在 main 之前定义。这是否有效,因为 int getData()
的默认存储 class 是 extern
?如果是这样,为什么还要费心看下面的例子(类似于我在工作中看到的)?
main2.c
#include <stdio.h>
#include "externs.h"
int data;
int main()
{
data = 6;
printf("%d\n", getData());
data = 8;
printf("%d\n", getData());
return 0;
}
externs.h
#ifndef _EXTERNSH_
#define _EXTERNSH_
extern int getData();
#endif
externs.c
int getData()
{
extern int data;
return data;
}
bash
gcc main2.c externs.c -o externs
函数是隐式的 extern
。您可以通过将它们声明为 static
.
你是对的,说 extern int getData();
与 int getData();
相比是多余的,但有些人认为它提高了代码清晰度。
请注意,自 C99 起,您的第一个示例格式错误。它在未声明该函数的情况下调用 getData
。在 C89 中,这执行了一个隐式的 int getData();
声明,但从 C99 开始,它被删除了。使用编译器开关 -std=c99 -pedantic
进行测试。
默认情况下,GCC 版本 4.x 或更早版本在 C89/C90 兼容模式下编译,不需要在使用前声明函数。未声明的函数被推断为具有 return 类型的 int
。默认情况下,GCC 5.x 或更高版本在 C11 兼容模式下编译,这确实需要在使用前声明函数——C99 也是如此。
鉴于编译后的代码没有任何抱怨,我们可以推断您正在使用 GCC 4.x。
即使如此,您也没有义务提供完整的原型,尽管您不这样做是愚蠢的。我通常使用以下选项编译代码:
gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Wold-style-declaration …
我怀疑那里有一些冗余,但在我开始 运行 代码之前,这些选项会遇到很多问题。