【问题标题】:Why are function definitions implicitly external in C?为什么函数定义隐式在 C 中是外部的?
【发布时间】:2021-02-23 03:44:23
【问题描述】:

我读到 extern 关键字隐含在函数的上下文中,所以除非您另外指定使用 static 关键字(如果我没记错的话,它基本上是一个与 @ 完全不同的概念987654328@ 变量使用——它们只是共享一个关键字),它们对所有目标文件都是可见的。这是有道理的;将声明隐含在外部,虽然在声明与定义位于同一文件中时技术上没有必要,但它很有用,因为程序员不必在每次想要使用其定义文件中的函数时都键入 extern,情况往往如此。对我来说奇怪的是它是隐含的声明和定义

对于变量,我不需要在定义中包含extern,事实上,虽然我可以做到这一点而不会出错,但我的编译器会为此发出警告。

例如,我可以有mylib.h:

int var = 5;

//it isn't necessary to write this as
//extern int var = 5;
//my compiler even warns against it

test.c

#include "mylib.h"

extern int var;

我通常会假设函数的隐式extern 是相同的,也就是说,如果我在mylib.h 中定义了int func(int par),则在它之前不会有隐式extern,但会有一个隐含的extern 用于任何声明(例如,如果我声明它用于test.c)。

extern 关键字的角度来看,它也没有多大意义,它被用作告诉编译器在其他地方寻找定义的一种方式,而定义永远不会在它所在的文件之外。

我觉得我在这里遗漏了一些东西。

【问题讨论】:

  • 也许我误解了你的问题,但在我看来你这样做是错误的。将int var 放入h 文件并将extern int var 放入c 文件不是通常的方法。不确定这些 Q 是否是骗子,但我认为您可以通过阅读找到所需的信息:stackoverflow.com/q/1433204/4386427stackoverflow.com/q/1410563/4386427
  • 如果您在mylib.h 中写入int var = 5;,那么它定义了变量。在任何给定的程序中,只有一个文件可以包含 mylib.h — 如果多个文件包含标题,则会出现多重定义错误。默认情况下,使用 GCC 10.x,即使您在标头中写入 int var;(而不是 extern int var;),最终也会出现多个定义错误——尽管旧版本的 GCC 默认情况下不会这样做。跨度>
  • 变量和函数的static 关键字限制了命名对象的可见性。有一些区别——例如,你可以在函数中使用静态变量。但是这些概念非常相似,以至于说 "[static应用于函数] 基本上是一个与变量使用的static 完全不同的概念 至少是夸大了。
  • @thepufferfish 从您链接的图片中,很明显这本书正在讨论两个不同的源文件(又名 c 文件)。它不是在谈论一个 h 文件和一个 c 文件。

标签: c function extern function-definition


【解决方案1】:

如果您在任何头文件中使用int x = 10;,那么您将遇到麻烦,因为如果您在与test.c 链接的任何其他文件(.c.h)中包含相同的头文件,那么你会得到一个错误redefinition of variable x

你可以自己试试。

所以始终将extern int x; 保留在头文件中, 并在任何.c 文件中定义它int x = 10;

所以,在这种情况下,如果你在多个地方包含头文件,那很好,因为头文件只有一个声明,你可以在多个地方声明同一个变量,没有任何问题。

你可以试试这个示例程序来测试错误multiple definition of `global_value'

测试.h

extern int global_value;

test.c

#include <stdio.h>
#include "test.h"
int global_value = 10;

int test_func()
{
        printf("golbal_value = %d", global_value);
        global_value = 20; // changed here, reflect in main after test_func call
}

main.c

#include <stdio.h>
#include "test.h"
int main()
{
        test_func();
        printf("global_value = %d\n", global_value);
        return 0;
}

上述程序完美运行。得到错误将extern int global_value; 带到test.cint global_value = 10;test.h 并编译在一起gcc test.c main.c

【讨论】:

  • 谢谢,这真的帮助我更好地理解为什么标题不应该包含全局变量定义。据我了解,由于在预处理过程中将头文件附加到源文件中,因此您基本上可能会遇到麻烦,因为每个源文件都定义了该全局变量,从而使编译器感到困惑。我想如果你在一个源文件中包含两次标题,如果你没有包含保护,理论上你可能会遇到同样的问题;虽然我猜如果你的标题没有包含保护,那是一个大问题。
  • 所以,我只是想到了一些事情。如果在头文件中定义全局变量时存在与自身冲突的问题,这是否意味着,考虑到函数中隐含的extern,除非您在头文件中将函数定义为static,否则会有同样的问题?也就是函数最好在header中声明,但是如果在header里面定义的话,很可能会出问题?
  • 通常我们不会在头文件中声明static 函数,因为我们希望在一个单独的.c 中使用静态函数,而不是在文件之外。所以我们在.c 本身中声明它们高于所有其他语句。
猜你喜欢
  • 2011-04-30
  • 2011-12-16
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多