1

我最近开始意识到强烈建议使用“extern”关键字。因此,我开始怀疑我使用头文件的当前(无外部)方式是否有任何问题:

主.c:

#include "main.h"
#include "function.h"

int main(void){
    globalvariable = 0;

    testfunction();
    return 0;
}

主.h:

#ifndef MAIN_H_
#define MAIN_H_

int globalvariable;

#endif /* MAIN_H_ */

函数.c:

#include "main.h"
#include "function.h"

void testfunction(){
    globalvariable++;
    return;
}

函数.h:

#ifndef FUNCTION_H_
#define FUNCTION_H_

void testfunction(void);

#endif /* FUNCTION_H_ */

因此,每个需要访问globalvariable的新源文件只需要包含 main.h。

这种方法的一个明显缺点是数组:一旦声明了数组,就不能使用 {element0, element1, ...} 格式为数组赋值。

顺便说一句,当我给globalvariable一个初始值为零时,我是在那个时候定义它吗?还是更早分配内存?

另外,我使用的方法有官方术语吗?

4

5 回答 5

2

您的代码的缺点是您可能会收到链接器错误。1


1. “可能”是基于在一大堆不同的工具链上构建代码的概念。

于 2012-04-09T20:24:17.810 回答
2

这样做的问题是,当您尝试链接程序时,可能会由于多个定义而出现链接错误。您在这里取决于实现定义的行为 - 允许实现将重复定义视为全部引用单个对象,但不是必需的。

于 2012-04-09T20:25:59.477 回答
2
extern int globalvariable;

是一个声明

int globalvariable;

既是声明又是暂定定义

在 C 中,同一个变量有多个定义是非法的,如果您在包含在多个翻译单元中的头文件中使用后者,就会发生这种情况。

然而,Unix 系统在历史上允许这种用法,因此大多数编译器都会接受该代码,尽管它是无效的 C。

于 2012-04-09T20:26:13.160 回答
2

对于您使用的方法,我知道的唯一官方术语是“实现依赖行为”。一旦您开始使用不同的编译器(甚至可能是同一编译器的不同版本)进行构建,您将遇到该方法的各种问题。有些会抛出链接器错误,但有些会接受它(尽管不能保证它会如何解释)。我强烈建议您采用更标准的方法,编译器将以可预测的方式进行解释。

变量的定义需要在 .c 文件中。如果要从另一个 .c 文件访问该变量,请在标题中添加extern 声明。这种技术是标准的 C 语言,可以在任何符合标准的编译器上进行可预测的解释。

为了回答您的分配问题,在程序开始运行之前分配了所有全局变量的内存。全局变量即使只用在从不运行的代码的子部分中也会占用空间。您的globalvariable = 0;行实际上并没有给变量一个初始值。C 编译器将确保所有未初始化的全局变量在程序加载时自动初始化为零。您的代码在技术上重新分配了变量的值。如果要确保将全局初始化为特定值,请将初始化程序添加到定义中,例如int globalvariable = 42;.

于 2012-04-09T21:17:17.780 回答
0

ANSI C 标准说

如果对象标识符的声明具有文件范围且没有存储类说明符,则其链接是外部的。

于 2014-07-20T13:25:13.347 回答