c语言中的extern关键字

问题描述 投票:0回答:1

我知道

extern
的一些基本用法,但有一件事确实困扰着我。
下图是我在规格书中找到的。

img1 img2

如果真的如图所示,为什么下面两段代码不一样?

#include <stdio.h>

int i;

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

extern int i;

int main() {
    printf("i = %d\n", i);
    return 0;
}

另外,下面的代码会有警告:

警告:“i”已初始化并声明为“extern”

为什么?

extern int i = 0;

谁能告诉我

extern
到底是怎么回事?

c extern
1个回答
0
投票

图像中的文本是错误的,因为“extern”和“auto”不是存储类。

extern
auto
是C语法中的存储类关键字,但C链接的类型是externalinternalnone,存储类的类型是staticthread 自动分配。这种区别很重要,因为存储类关键字不仅仅与存储类或链接相关;它还与存储类关键字相关。它们因 C 开发的历史而变得复杂。

在文件范围内,

int i;
是名为 i 的对象的
临时定义
。尽管有它的名字,“暂定定义”并不是一个定义(就像工作面试中的潜在雇员不是雇员一样)。如果翻译单元中不存在常规定义,则暂定定义将导致创建定义。然而,由于不同的 C 实现对 int i; 的处理方式不同,C 标准没有定义如果有多个定义会发生什么。一些 C 实现将兼容的临时定义产生的多个定义合并为单个定义。有些人将它们视为错误。 GCC 版本 10 中的默认值已更改。
在文件范围内,

extern int i;

是名为

i
的对象的 声明,该对象不是定义。它不会为
i
保留存储空间,并且,如果在程序中使用
i
,则必须在程序的其他位置对其进行定义。
在文件范围内,

extern int i = 0;

是名为

i
的对象的 定义。根据 C 标准的规则,带有初始化的声明也是一个定义,即使它有
extern
,因此编译器应该将其视为定义。然而,C 用户的惯例是使用
extern
来区分不是定义的声明。因此,用
int i
声明
extern
并用
= 0
提供初始化违反了该约定。但该约定不是 C 的规则。因此编译器会警告这种违反约定的行为,但符合 C 标准的编译器必须接受此代码作为
i
的定义。 (如果您将警告变成错误,就像 Clang 或 GCC 中的
-Werror
开关一样,编译器不接受此代码并成为不合格编译器。)
    

© www.soinside.com 2019 - 2024. All rights reserved.