c - 允许静态声明后跟非静态声明的基本原理,但反之则不然

标签 c static declaration extern

此代码将在当前 C 标准下编译并定义良好:

static int foo(int);
extern int foo(int);

标准规定在这种情况下(C11:6.2.2 标识符链接 (p4)):

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. [...]

...这意味着 int foo(int) 函数被声明为 static int foo(int)

像这样交换这些声明:

extern int foo(int);
static int foo(int);

...使用 GNU GCC 时出现编译器错误:

static declaration of 'foo' follows non-static declaration

我的问题是:第二种情况是错误并且没有以与第一种情况类似的方式处理的设计原理是什么?我怀疑这与以下事实有关:单独的翻译单元更易于管理,并且#include?我觉得如果不理解这一点,我可能会在未来的 C 项目中面临一些错误。

最佳答案

我认为这个令人困惑的规范的想法是,可以在函数内部使用 extern 声明来引用全局函数或对象,例如,消除它与另一个同名标识符的歧义

static double a; // a declaration and definition

void func(void) {
  unsigned a;
  .....
  if (something) {
     extern double a; // refers to the file scope object

  }
}

而如果你使用static,你就声明了一些新的东西:

extern double a;  // just a declaration, not a definition
                  // may reside elsewhere
void func(void) {
  unsigned a;
  .....
  if (something) {
     static double a; // declares and defines a new object

  }
}

关于c - 允许静态声明后跟非静态声明的基本原理,但反之则不然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43614828/

相关文章:

vb.net - Visual Basic 6.0 到 VB.NET 声明

c++ - 数组的维数是不是在创建数组的那一刻就确定了,并且以后不能更改?

c++ - 我如何在我的进程空间内 "mount"而不是 root?

Java:从线程操作非静态变量?

c++ - 是否可以在 C++ 的类中初始化静态常量成员对象?

c++ - 对 'WinMain@16' 的 undefined reference

c++ - 声明一个 const 变量作为引用

c - libxml2 解析问题 : Namespace error

c - 如何在循环中为数组设置特定值? - C

Java 类格式错误 : Method "<error>" class has illegal signature