2016-05-19 17 views
2

我正在阅读C项目的来源,并试图辨别为什么使用extern的特定用途。 (注:This question是相关的,但对于C++,不C.)说我有四个头文件,每个声明一个extern const结构:使用与定义相同的文件中的extern声明的好处?

extern const struct puppy fido; 

这个结构是在源文件中定义像这样:

extern const struct puppy fido; 
static const struct puppy *puppies[] = { &fido }; 
const struct puppy fido = { "fido", 10, 10 }; 

如果在源文件中将变量声明标记为extern,那么在那些变量在同一个源文件中定义时是否有某种好处?

+0

我认为这个帖子可能有所帮助:http://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files-in-c –

+0

请澄清一下,我是否正确理解这一点:你有4个带有extern声明的头文件和1个包含extern声明和定义的.c文件? – Lundin

+0

@Lundin这是正确的。 – ybakos

回答

1

Lundin是正确的,在这种情况下,extern不会影响fido在其他源文件中的可见性。在您的示例代码中,它用作前向声明。

有关部分从C99标准,第6.2.2节:

4)对于在范围存储类说明的extern声明的标识符,其中该标识符的先前声明是可见的,如果先前的声明规定了内部或外部的链接,后面声明中标识符的链接与先前声明中指定的链接相同。如果前面的声明不可见,或者前面的声明没有指定链接,则标识符具有外部链接。

5)如果一个函数的标识符声明没有存储类说明符,那么它的链接就像使用存储类说明符extern声明一样。如果一个对象的标识符的声明有文件范围和没有存储类说明, 其连接是外部

在C++中,行为将是不同的,因为与const声明的变量隐含static。在C++中,您需要首次使用extern声明该变量,否则其他编译单元将无法找到它。

C++ 98标准,部分3.5.3:

的名称具有命名空间范围(3.3.5)具有内部连接,如果它是

名称 - 一个对象,参考,函数或函数模板明确声明为静态的,或者明确声明为const的对象或引用,既不明确声明为extern,也不声明为具有外部链接;

+2

FWIW,声明不带静态的内部变量被标记为C中的过时特征。C11 6.11.2标识符的链接:“在没有静态存储类说明符的情况下,在文件范围声明带有内部链接的标识符是过时的功能。 – Lundin

+0

这是一个C语言问题,你为什么一直在谈论其他语言 –

+1

@ M.M有人可能在将来搜索这个,而不会以不同的方式实现C和C++的工作。 –

-1
extern const struct puppy fido; 
// ... 
const struct puppy fido = { "fido", 10, 10 }; 

如果const struct puppy fido = { "fido", 10, 10 };被编译为2个不同的.c文件,则会失败。在const struct puppy fido = { "fido", 10, 10 };之前和之后应该有#ifndef和以包括它一次。

一个好的做法(全局变量具有一般要避免的)是在.h文件extern申报,并把变量的定义在.c文件。

+0

ifndef/endif不能解决跨2个不同c文件编译的问题。我不知道你在说什么 –

+0

@ M.M:它假设你在c文件中使用'#define DECLARE_MY_CONST_FIDO',然后包含这个头文件。 'const struct ...'只会写在这个文件中。如果const声明不在'#ifdef DECLARE_MY_CONST_FIDO'文件中,那么如果文件包含在几个.c文件中,它肯定会失败。 –

+0

好的,也许在你的答案中包含示例代码。这是一种不寻常的技术,所以人们不会知道你在说什么 –

3

唯一的好处是声明和定义之间的任何代码都可以访问变量。除此之外,同一个文件中的外部声明是毫无意义的。

+1

我认为'extern'不是必须的。但它看起来像一个“*前置声明*”。 –

+1

此外,有些人认为,即使没有特定的原因需要“前向声明”,也可以在文件中将所有静态变量的声明放在顶部附近,这是很好的代码组织方式 –

+0

虽然声明允许访问变量在定义之前,它没有回答关于在声明中使用'extern'的问题。 – ybakos

0

有时候,当你编写一个源文件时,你只需要一段头文件,而不是整件事情。

重复源文件中的extern声明允许您不要在该特定源文件中包含头文件。

这不一定是一个好习惯。

相关问题