作者loveflames (咕啾咕啾魔法陣)
看板C_and_CPP
標題Re: [問題] 該怎麼做才能正確的把標頭檔內的函式引 …
時間Mon Nov 15 02:53:50 2010
※ 引述《qrtt1 (null)》之銘言:
: 標題: Re: [問題] 該怎麼做才能正確的把標頭檔內的函式引 …
: 時間: Sun Nov 14 22:16:05 2010
:
: 另一種產生錯誤的情況是,一個變數被重複定義。
: 這通常會發生在 header 第二次被引用時,
: 常是忘了在 header 內只寫宣告的原則。
:
: 若我們將 featureA.h 內的
:
: int featureA;
:
: 改寫成
:
: int featureA = 0;
:
: 您就會得到這樣的錯誤:
:
: gcc main.c featureA.o
: featureA.o:(.bss+0x0): multiple definition of `featureA'
: /tmp/ccIWzIWE.o:(.bss+0x0): first defined here
: collect2: ld 回傳 1
: make: *** [all] Error 1
:
: 只要善用前置處理器以及不在 header 內定義變數、函式,
: 就能與 header 合平共存。
:
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ◆ From: 61.231.52.57
: 推 loveflames:int featureA是定義,不過放在header不會出現重覆定義 11/14 22:44
: → loveflames:的錯誤,除非給它初值 11/14 22:45
: → loveflames:忘了說C語言限定 11/14 22:45
: 推 purpose:就 header 內寫 extern int featureA; 11/14 23:00
: 推 loveflames:只有C++才要加extern吧 11/14 23:06
: 推 purpose:覺得加了比較保險 11/14 23:28
: → manlike:一定要加extern吧 除非你這個.h只會被一個檔案include = = 11/15 01:44
: → manlike:不對 沒看仔細 = =" 11/15 01:46
: → manlike:像這種global變數通常會宣告定義在.c內 .h宣告extern = = 11/15 01:50
找了一下GNU ld的說明
`int i = 1;'
A definition, which goes in the initialized data section of the output file.
`extern int i;'
An undefined reference, which does not allocate space. There must be either a
definition or a common symbol for the variable somewhere.
`int i;'
A common symbol. If there are only (one or more) common symbols for a
variable, it goes in the uninitialized data area of the output file. The
linker merges multiple common symbols for the same variable into a single
symbol. If they are of different sizes, it picks the largest size. The linker
turns a common symbol into a declaration, if there is a definition of the
same variable.
windows下的結果也一樣
但沒找到common symbol的說明就是了
規格書也有寫
6.9.2 External object definitions
Semantics
1 If the declaration of an identifier for an object has file scope and an
initializer, the
declaration is an external definition for the identifier.
2 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.
3 If the declaration of an identifier for an object is a tentative definition
and has internal
linkage, the declared type shall not be an incomplete type.
J.5 Common extensions
1 The following extensions are widely used in many systems, but are not
portable to all
implementations. The inclusion of any extension that may cause a strictly
conforming
program to become invalid renders an implementation nonconforming. Examples
of such
extensions are new keywords, extra library functions declared in standard
headers, or
predefined macros with names that do not begin with an underscore.
J.5.11 Multiple external definitions
1 There may be more than one external definition for the identifier of an
object, with or
without the explicit use of the keyword extern; if the definitions disagree,
or more than one is initialized, the behavior is undefined (6.9.2).
簡單講就是前面沒有storage-class或static等修飾詞
而且也沒初值的話
就視為tentative definition
如果其他地方也沒給初值
初始值就給0
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.252.66.243
※ 編輯: loveflames 來自: 111.252.66.243 (11/15 04:20)
→ tinlans:我記得在 C99 Rationale 還看過一張比較表,蠻清楚的。 11/15 05:06
→ tinlans:是啊,樓上真會找 XD 11/15 06:30
→ qrtt1:感謝分享啊:D 11/15 07:16