【问题标题】:Why do I need to declare this function extern. It works without it为什么我需要声明这个函数extern。没有它也能工作
【发布时间】:2023-09-04 13:41:01
【问题描述】:

我对外部概念不熟悉。今天在工作中,我遇到了大量在头文件中声明的外部函数; foo.h.在一堆文件夹的某个地方,我找到了一个 foo.c 文件,其中包含所述函数的定义,但它没有 #include foo.h。回到家后,我决定尝试使用外部存储类示例。在“C书”中做了一些阅读之后,这就是我想出的。

这是我没想到的。但确实如此。

ma​​in.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;
}

重击

gcc main.c externs.c -o externs

我认为这不会起作用,因为该函数在技术上(或至少是冗长的)在 main 之前没有定义。这是否可行,因为int getData() 的默认存储类是extern?如果是这样,为什么还要费心下面的例子(类似于我在工作中看到的)?

ma​​in2.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;
}

重击

gcc main2.c externs.c -o externs

【问题讨论】:

  • 能否在每种情况下添加或评论输出?

标签: c scope extern storage-class-specifier


【解决方案1】:

函数是隐含的extern。您可以通过将它们声明为 static 来更改此设置。

你说得对,说extern int getData();int getData(); 相比是多余的,但有些人认为它提高了代码清晰度。

请注意,从 C99 开始,您的第一个示例格式不正确。它在没有声明该函数的情况下调用getData。在 C89 中,这执行了一个隐式的 int getData(); 声明,但从 C99 开始,它被删除了。使用编译器开关-std=c99 -pedantic 进行测试。

【讨论】:

    【解决方案2】:

    默认情况下,GCC 4.x 或更早版本以 C89/C90 兼容模式编译,该模式不需要在使用前声明函数。未声明的函数被推断为具有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 …
    

    我怀疑其中存在一些冗余,但在我开始运行代码之前,这些选项会发现很多问题。

    【讨论】:

    • 感谢您的回答。 +1 为 gcc 标签。毫米。领先你 1 分钟 :x
    最近更新 更多