2012-04-09 61 views
1

我最近开始意识到,强烈建议使用“extern”关键字。因此,我开始怀疑是否有什么毛病电流(EXTERN少)的方式我使用头文件:在没有“extern”关键字的头文件中声明变量是否有任何缺点?

的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_ */ 

因此,每个需要访问全局变量的新源文件都只需要包含main.h。

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

顺便说一下,当我给全局变量初始值为零,我在那个点上定义它?或者是先前分配的内存?

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

+0

'extern'关键字没有被高度鼓励;你只能在绝对必须的时候才使用它(希望永远不会)。 – 2012-04-09 20:23:40

+0

http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c – cnicutar 2012-04-09 20:24:20

+0

[全局变量不好](http://c2.com/cgi/wiki?GlobalVariablesAreBad)。 – 2012-04-09 20:24:28

回答

2

唯一的官方术语,我知道的方法,你正在使用的“实施有关的行为”的大多数编译器将接受该代码。一旦你开始用不同的编译器(或者甚至可能是不同版本的编译器)开始构建,你将遇到各种各样的问题。有些人会抛出链接器错误,但有些人会接受它(尽管不能确切地解释它将如何解释)。我强烈建议你采用更为标准的方法,编译器将以可预测的方式进行解释。

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

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

+0

我在这个答案和“R ..”之间撕裂。由于回复了我原来的帖子的所有部分,这款游戏赢了。 – SharpHawk 2012-04-10 16:26:07

1

你的代码的缺点是你可能会得到一个链接错误。


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

+0

你是否真的认为我会继续这样做,如果它导致链接器错误? – SharpHawk 2012-04-09 20:31:13

+0

@SharpHawk:你有没有试过,比如说MSVC? – 2012-04-09 20:36:20

+0

不,我只在AVR Studio 5中使用它(这是一个非常糟糕的程序)。 – SharpHawk 2012-04-09 20:39:06

1

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

2
extern int globalvariable; 

声明

int globalvariable; 

既是一个声明和一个暂定定义

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

Unix系统历史上允许这种用法,所以尽管它是无效C.

+0

你是什么意思“在一个包含在多个翻译单元中的头文件中使用后者”?会有多个源文件包含该头文件数量?如果是这样,那就是我正在做的事情,正如你在最后一行所述,编译器不会抱怨。事实上,它甚至不会产生警告。 – SharpHawk 2012-04-09 20:36:44

+0

对。编译器不能抱怨,因为每个单独的翻译单元都是有效的;只有链接器可以投诉,而不是,因为它在传统的UNIX上允许这样做。这仍然不能使它有效C,而且它没有做你想做的事。 (它在链接时将变量的多个定义合并成一个,而不是声明你想访问在另一个翻译单元中定义的变量。) – 2012-04-09 20:43:15

0

ANSI C标准说

如果一个对象的标识符的声明有文件范围和 没有存储类说明,其连接是外部的。

相关问题