我最近开始意识到强烈建议使用“extern”关键字。因此,我开始怀疑使用头文件的当前(extern-less)方式是否有任何问题:
main.c中:
#include "main.h"
#include "function.h"
int main(void){
globalvariable = 0;
testfunction();
return 0;
}
main.h:
#ifndef MAIN_H_
#define MAIN_H_
int globalvariable;
#endif /* MAIN_H_ */
function.c:
#include "main.h"
#include "function.h"
void testfunction(){
globalvariable++;
return;
}
function.h:
#ifndef FUNCTION_H_
#define FUNCTION_H_
void testfunction(void);
#endif /* FUNCTION_H_ */
因此,每个需要访问 globalvariable 的新源文件都需要包含main.h。
此方法的一个明显缺点是数组:一旦声明了数组,就不能使用{element0,element1,...}格式化为数组赋值。
顺便说一下,当我给 globalvariable 初始值为零时,我是否在那时定义它?或者是之前分配的内存?
另外,我正在使用的方法是否有官方用语?
答案 0 :(得分:2)
extern int globalvariable;
是声明
int globalvariable;
既是声明又是暂定定义。
在C中,同一个变量有多个定义是非法的,如果你在一个包含在多个翻译单元中的头文件中使用后者,就会发生这种情况。
然而,Unix系统在历史上允许这种用法,因此大多数编译器都会接受代码,尽管它是无效的C.
答案 1 :(得分:2)
我所知道的唯一正式术语是“依赖于实现的行为”。一旦开始使用不同的编译器(或者甚至可能是同一编译器的不同版本),您将遇到该方法的各种问题。有些会抛出链接器错误,但有些人会接受它(虽然不能确切地解释它是如何解释的)。我强烈建议您采用更标准的方法,编译器将以可预测的方式解释。
变量的定义需要位于.c文件中。如果要从另一个.c文件访问该变量,请在标头中添加extern
声明。这种技术是标准的C,可以在任何符合标准的编译器上进行可预测的解释。
要回答您的分配问题,在程序开始运行之前会分配所有全局变量的内存。全局变量占用空间,即使它仅用于从不运行的代码的子部分。您的globalvariable = 0;
行实际上并未向变量提供初始值。 C编译器将确保在程序加载时所有未初始化的全局变量自动初始化为零。您的代码在技术上重新分配变量的值。如果要确保将全局初始化为特定值,请将初始化程序添加到int globalvariable = 42;
等定义中。
答案 2 :(得分:1)
您的代码的缺点是您可能会收到链接器错误。 1
<小时/> <子> 1。 “可能”的基础是在一大堆不同的工具链上构建代码的概念。
答案 3 :(得分:1)
这样做的问题是,当您尝试链接程序时,可能会因多个定义而导致链接错误。您在此处依赖于实现定义的行为 - 允许实现将重复定义视为所有引用单个对象,但不是必需的。
答案 4 :(得分:0)
ANSI C标准说
如果对象的标识符声明具有文件范围和 没有存储类说明符,它的链接是外部的。