在C头文件中定义变量相关的疑问 [英] Defining variable in C header file related doubt

查看:58
本文介绍了在C头文件中定义变量相关的疑问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到一个程序源代码,其中一个变量在头文件中定义

文件,该头文件包含在2个不同的C文件中。当我

编译时并链接文件没有错误被抛出。这是怎么可能的。我认为它会抛出变量重新定义错误。给

源代码以供参考。请帮我解决这个问题...




-----

int g;

虚无趣(无效);


ac

---- -

#include" a.h"

void main()

{

g = 50; < br $> b $ b printf("%d \ n",g);

fun();

printf("%d \ n" ;,g);

}


bc

----

#include" ; a.h"

虚假乐趣(无效)

{

g = 120;

}


输出为50 ... 120

问候

Manu

I saw a program source code in which a variable is defined in a header
file and that header file is included in 2 different C files.When i
compile and link the files no error is being thrown.How is this
possible.I thought it will throw "Variable redefinition Error". Giving
the source code for reference.Please help me out on this...

a.h
-----
int g;
void fun(void);

a.c
-----
#include "a.h"
void main()
{
g = 50;
printf("%d\n",g);
fun();
printf("%d\n",g);
}

b.c
----
#include "a.h"
void fun(void)
{
g = 120;
}

Output is 50...120

Regards
Manu

推荐答案

whirlwindkevin说:
whirlwindkevin said:

我看到一个程序源代码,其中一个变量在标题中定义

文件和该头文件包含在2个不同的C文件中。
I saw a program source code in which a variable is defined in a header
file and that header file is included in 2 different C files.



显然它没有编译。

And it didn''t compile, obviously.


当我

编译并链接文件没有抛出错误。
When i
compile and link the files no error is being thrown.



然后你没看到你以为你看到了什么。

Then you didn''t see what you thought you saw.


这是怎么回事? />
possible.I以为它会抛出Variable redefinition Error。给

源代码以供参考。请帮我解决这个问题...




-----

int g;
How is this
possible.I thought it will throw "Variable redefinition Error". Giving
the source code for reference.Please help me out on this...

a.h
-----
int g;



这不是*完全*定义。它是一个暂定的定义,而且它是C中最愚蠢的想法之一 - 这是该语言的一个愚蠢的特征,并且

愚蠢的程序员利用这个功能。


一些术语:

A *声明*你告诉编译器看到这个标识符?当我用
使用它时,我说的是这种类型的对象(或函数),

并且只相信我这个对象存在好吗?基于这种理解,一个

编译器可以继续编译甚至可以与对象进行交互的代码

或者它现在看不到的函数(就像木匠一样)即使没有看到通过它会丢弃的实际字母,也可以在门上制作一个

信箱,只要你告诉他这些字母有多大)。但如果你对编译器撒谎,你会稍后付款。


A * definition *你告诉编译器让我成为一个对象

这样一种类型 (或执行此操作的功能)。如果声明

是一个承诺,那么定义就是兑现承诺的一种方式。一个

定义*是一个声明(因为,当你创建一个对象时,'

和任何通知编译器对象存在的方式一样好),

但声明不一定是定义。


A暂定定义你告诉编译器它是我的意图

创建这种类型的对象,但我不确定这是否是

对吧做到这一点的地方。标准说:


"具有文件范围的对象的标识符声明

没有初始化程序,没有存储类说明符或使用

存储类说明符static,构成暂定的

定义。如果翻译单元包含一个或多个用于标识符的暂定

定义,并且翻译单元不包含该标识符的外部定义,那么行为恰好是

,好像翻译单元包含该

标识符的文件范围声明,其复合类型截至翻译结尾

单位,初始化程序等于0.


最佳建议?像瘟疫一样避免。相反,如果你必须使用文件范围

对象标识符,那就这样做:


1)在一个标题中,所有相关来源都可以包含,

写一个声明,例如:


extern int IfYouMustDoThisDamnSillyThing;


2)在同一个标​​题中,为对象定义合理的初始值:


#define DO_IT_LIKE_THIS 42

3)在所有相关来源中包含该标题;

int IfYouMustDoThisDamnSillyThing = DO_IT_LIKE_THIS;

This is not *exactly* a definition. It''s a "tentative definition", and it''s
one of the silliest ideas in C - a silly feature of the language, and
silly of the programmer to exploit the feature.

Some terms:
A *declaration* is you telling the compiler "see this identifier? When I
use it, I''m talking about an object (or function) of such-and-such a type,
and just trust me that this object exists, okay?" On that understanding, a
compiler can go ahead and compile code that can interact even with objects
or functions that it can''t see right now (much as a carpenter can make a
letterbox in a door even without seeing the actual letters that will drop
through it, provided you tell him how big the letters will be). But if you
lie to the compiler, you''ll pay later.

A *definition* is you telling the compiler "make me an object of
such-and-such a type" (or a "function that does THIS"). If a declaration
is a promise, then a definition is a way of honouring that promise. A
definition *is* a declaration (because, when you create an object, that''s
as good a way as any of informing the compiler that the object exists),
but declarations need not be definitions.

A "tentative definition" is you telling the compiler "it''s my intent to
create an object of this type, but I''m not really sure whether this is the
right place to do it". The Standard says:

"A declaration of an identifier for an object that has file scope
without an initializer, and without a storage-class specifier or with
the storage-class specifier static , constitutes a tentative
definition. If a translation unit contains one or more tentative
definitions for an identifier, and the translation unit contains no
external definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation
unit, with an initializer equal to 0."

Best advice? Avoid like the plague. Instead, if you must use file scope
object identifiers, do it this way:

1) in exactly one header that can be included by all relevant sources,
write a declaration, such as:

extern int IfYouMustDoThisDamnSillyThing;

2) in the same header, define a sensible initial value for the object:

#define DO_IT_LIKE_THIS 42

3) include that header in all relevant sources;

4) in exactly one source, write a definition at file scope, such as:

int IfYouMustDoThisDamnSillyThing = DO_IT_LIKE_THIS;


void main()
void main()



main函数返回int。如果你从main返回任何其他东西,

你违反了C的规则,并且C免除了任何可以预测的b $ b的义务。
< br $>
-

Richard Heathfield< http://www.cpax.org.uk>

电子邮件:-http:// www。 + rjh @

谷歌用户:< http://www.cpax.org.uk/prg/writings/googly.php>

Usenet是一个奇怪的放置" - dmr 1999年7月29日

The main function returns int. If you return anything else from main,
you''re breaking the rules of C, and C is released from any obligation to
be predictable.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999


6月9日下午12:27,Richard Heathfield< r ... @ see.sig.invalidwrote:
On Jun 9, 12:27 pm, Richard Heathfield <r...@see.sig.invalidwrote:

whirlwindkevin说:
whirlwindkevin said:

我看到一个程序源代码,其中一个变量在标题中定义

文件和该头文件包含在2个不同的C文件中。
I saw a program source code in which a variable is defined in a header
file and that header file is included in 2 different C files.



它显然没有编译。


And it didn''t compile, obviously.


当我

编译并链接文件没有抛出错误。
When i
compile and link the files no error is being thrown.



然后你没看到你以为你看到了什么。


Then you didn''t see what you thought you saw.


这是怎么回事? />
possible.I以为它会抛出Variable redefinition Error。给

源代码以供参考。请帮我解决这个问题...
How is this
possible.I thought it will throw "Variable redefinition Error". Giving
the source code for reference.Please help me out on this...


ah

-----

int g;
a.h
-----
int g;



这不是*完全*定义。它是一个暂定的定义,而且它是C中最愚蠢的想法之一 - 这是该语言的一个愚蠢的特征,并且

愚蠢的程序员利用这个功能。


一些术语:

A *声明*你告诉编译器看到这个标识符?当我用
使用它时,我说的是这种类型的对象(或函数),

并且只相信我这个对象存在好吗?基于这种理解,一个

编译器可以继续编译甚至可以与对象进行交互的代码

或者它现在看不到的函数(就像木匠一样)即使没有看到通过它会丢弃的实际字母,也可以在门上制作一个

信箱,只要你告诉他这些字母有多大)。但如果你对编译器撒谎,你会稍后付款。


A * definition *你告诉编译器让我成为一个对象

这样一种类型 (或执行此操作的功能)。如果声明

是一个承诺,那么定义就是兑现承诺的一种方式。一个

定义*是一个声明(因为,当你创建一个对象时,'

和任何通知编译器对象存在的方式一样好),

但声明不一定是定义。


A暂定定义你告诉编译器它是我的意图

创建这种类型的对象,但我不确定这是否是

对吧做到这一点的地方。标准说:


"具有文件范围的对象的标识符声明

没有初始化程序,没有存储类说明符或使用

存储类说明符static,构成暂定的

定义。如果翻译单元包含一个或多个用于标识符的暂定

定义,并且翻译单元不包含该标识符的外部定义,那么行为恰好是

,好像翻译单元包含该

标识符的文件范围声明,其复合类型截至翻译结尾

单位,初始化程序等于0.


最佳建议?像瘟疫一样避免。相反,如果你必须使用文件范围

对象标识符,那就这样做:


1)在一个标题中,所有相关来源都可以包含,

写一个声明,例如:


extern int IfYouMustDoThisDamnSillyThing;


2)在同一个标​​题中,为对象定义合理的初始值:


#define DO_IT_LIKE_THIS 42

3)在所有相关来源中包含该标题;


4)在一个来源中,在文件范围内写一个定义,例如:


int IfYouMustDoThisDamnSillyThing = DO_IT_LIKE_THIS;


This is not *exactly* a definition. It''s a "tentative definition", and it''s
one of the silliest ideas in C - a silly feature of the language, and
silly of the programmer to exploit the feature.

Some terms:
A *declaration* is you telling the compiler "see this identifier? When I
use it, I''m talking about an object (or function) of such-and-such a type,
and just trust me that this object exists, okay?" On that understanding, a
compiler can go ahead and compile code that can interact even with objects
or functions that it can''t see right now (much as a carpenter can make a
letterbox in a door even without seeing the actual letters that will drop
through it, provided you tell him how big the letters will be). But if you
lie to the compiler, you''ll pay later.

A *definition* is you telling the compiler "make me an object of
such-and-such a type" (or a "function that does THIS"). If a declaration
is a promise, then a definition is a way of honouring that promise. A
definition *is* a declaration (because, when you create an object, that''s
as good a way as any of informing the compiler that the object exists),
but declarations need not be definitions.

A "tentative definition" is you telling the compiler "it''s my intent to
create an object of this type, but I''m not really sure whether this is the
right place to do it". The Standard says:

"A declaration of an identifier for an object that has file scope
without an initializer, and without a storage-class specifier or with
the storage-class specifier static , constitutes a tentative
definition. If a translation unit contains one or more tentative
definitions for an identifier, and the translation unit contains no
external definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation
unit, with an initializer equal to 0."

Best advice? Avoid like the plague. Instead, if you must use file scope
object identifiers, do it this way:

1) in exactly one header that can be included by all relevant sources,
write a declaration, such as:

extern int IfYouMustDoThisDamnSillyThing;

2) in the same header, define a sensible initial value for the object:

#define DO_IT_LIKE_THIS 42

3) include that header in all relevant sources;

4) in exactly one source, write a definition at file scope, such as:

int IfYouMustDoThisDamnSillyThing = DO_IT_LIKE_THIS;


void main()
void main()



main函数返回int。如果你从main返回任何其他东西,

你违反了C的规则,并且C免除了任何可以预测的b $ b的义务。
< br $>
-

Richard Heathfield< http://www.cpax.org.uk>

电子邮件:-http:// www。 + rjh @

谷歌用户:< http://www.cpax.org.uk/prg/writings/googly.php>

Usenet是一个奇怪的放置" - - 1999年7月29日dmr


The main function returns int. If you return anything else from main,
you''re breaking the rules of C, and C is released from any obligation to
be predictable.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999



非常感谢理查德回复...

我仍​​然对变量的定义有疑问.Can你告诉我b $ b $变量g(上面程序中的变量)是什么?定义了
(为变量分配空间)?它是ac还是b / b

Many Thanks Richard for replying...
Still i have a doubt related to definition of the variable.Can you
please tell where variable g (variable in the above program) is
defined (space is allocated for the variable)? Is it in a.c or is it
in b.c?


whirlwindkevin说:


< snip>
whirlwindkevin said:

<snip>

非常感谢理查德回复...

我还有一个与变量定义有关的疑问。你可以吗? />
请告诉变量g(上面程序中的变量)是哪个定义的(
)(为变量分配空间)?是在a.c还是在b.c中是

Many Thanks Richard for replying...
Still i have a doubt related to definition of the variable.Can you
please tell where variable g (variable in the above program) is
defined (space is allocated for the variable)? Is it in a.c or is it
in b.c?



不,不是真的。这就是为什么这是一个如此愚蠢的想法。再说一次,我建议你避免使用暂定的定义。


关于最多的可以说是编译器,看过

暂定定义,至少可以像声明一样对待它 - 并且一个

或其他暂定定义最终被视为

a定义。


-

Richard Heathfield< http://www.cpax.org.uk>

电子邮件:-http:/ /万维网。 + rjh @

谷歌用户:< http://www.cpax.org.uk/prg/writings/googly.php>

Usenet是一个奇怪的放置" - dmr 1999年7月29日

No, not really. That''s partly why it''s such a silly idea. Again, I
recommend that you avoid tentative definitions.

About the most that can be said is that the compiler, having seen a
tentative definition, can at least treat it like a declaration - and one
or other of the tentative definitions is eventually treated as if it were
a definition.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999


这篇关于在C头文件中定义变量相关的疑问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆