外部声明,T * V / S T [] [英] extern declaration, T* v/s T[]
问题描述
我看到一个旧的项目下面的一段code的。
/ * * token.c /
结构令牌id_tokens [MAX_TOKENS]/ * analyse.c(V1)* /
EXTERN结构令牌* id_tokens;提出了我的眉毛/ *,id_token声明了一个指针* /
我坚持改变 analyse.c
包含如下声明:
/ * analyse.c(V2)* /
EXTERN结构令牌id_tokens []; / *我很高兴这一点。 id_tokens声明未指定大小的数组。 * /
我想 V2
,因为指针至T
不一样的 T的数组
。我朋友的柜台argumented都是相同的这种行为,所以它不会不管我使用v1和v2。
问题1:是否不完整的类型的数组消耗的指针
问题2:是我的朋友的权利,这两个版本行为上保证等同
/ * * token.c /
结构令牌id_tokens [MAX_TOKENS]/ *
id_tokens
+ ----- + ----- + ----- + ----- + ... + ----- +
| | | | | | |
+ ----- + ----- + ----- + ----- + ... + ----- +
[0] [1] [2] [3] ... [MAX_TOKEN-1] 要访问id_tokens [I],第i个元素添加偏移
即I *的sizeof(结构令牌)的** **地址
阵令牌
* /
因此,在您 analyse.c
,将与这个声明会生成以下说明。
的extern结构令牌id_tokens [];
id_tokens [I]
一个。 id_tokens地址可能从其他编译单元链接
取
湾我的偏移量加到
℃。值引用
块引用>/ * analyse.c(V1)* /
EXTERN结构令牌* id_tokens;/ *
id_tokens
+ ------ + + ----- + ...
|地址| ----------> | |
+ ------ + + ----- + ...
要访问id_tokens [I],取** contetnts指针**
令牌,加入第i个元素的偏移,即我的sizeof *(结构令牌)
被添加到这一点。
* /因此,在您
analyse.c
,下面的说明将这一声明产生:
<醇开始=2>
的extern结构令牌* id_tokens;
id_tokens [I]
一个。从id_tokens地址的内容是从其他链接
编译单元取。
(会导致编译错误,如果因为类型不匹配的同一编译单元present)
湾我的偏移量加到
℃。
值引用
块引用>假设sizeof的
id_token [0]
是2
字节和sizeof指针id_token [0]
是4
字节。您稍后声明可(MIS)间$ P $私人的
id_tokens [0]
&安培;id_tokens [1]
作为一个地址,并添加一些偏移到它(这可能是现有的或不存在的地址,对齐或不对齐谁知道地址)。如果这是你的好日子,程序可能会崩溃或立即段错误,你会得到一个机会来修正错误。如果这是你糟糕的一天,节目可能只是乱用一些其他的内存或传达错误的状态的一些模块,这可能会导致难以跟踪的错误,并导致了一场噩梦。
现在我想你明白为什么你有
(无)
中的先生。 32的回答。I saw following piece of code in a legacy project.
/* token.c */ struct token id_tokens[MAX_TOKENS]; /* analyse.c (v1) */ extern struct token *id_tokens; /* Raised my eyebrow, id_token declares a pointer */
I insisted on changing
analyse.c
to contain the declaration as below:/* analyse.c (v2) */ extern struct token id_tokens[]; /* I am happy with this. id_tokens declares array of unspecified size. */
I want
v2
becausepointer to T
is not same asarray of T
. My friend's counter argumented that behaviour of both are same, so it doesn't matter whether I use v1 and v2.Question 1: Does array of incomplete type deplete to a pointer?
Question 2: Is my friend right that both versions are behaviorally guaranteed to be equivalent?
解决方案/* token.c */ struct token id_tokens[MAX_TOKENS]; /* id_tokens +-----+-----+-----+-----+...+-----+ | | | | | | | +-----+-----+-----+-----+...+-----+ [0] [1] [2] [3] ... [MAX_TOKEN-1] To access id_tokens[i], add offset of ith element i.e. i * sizeof(struct token) to the **address** of array token */
So in your
analyse.c
, following instructions would be generated with this declaration.
extern struct token id_tokens[];
id_tokens[i]
a. Address of id_tokens that might be linked from other compilation unit is taken
b. offset of i is added
c. Value is referenced
/* analyse.c (v1) */ extern struct token *id_tokens; /* id_tokens +------+ +-----+... | addr |---------->| | +------+ +-----+... To access id_tokens[i], fetch **contetnts** of pointer token, add offset of ith element i.e. i * sizeof(struct token) is added to this. */
So in your
analyse.c
, following instructions would be generated with this declaration:
extern struct token *id_tokens;
id_tokens[i]
a. Contents from address of id_tokens that is linked from other compilation unit is taken.
(Will result in compilation error if present in same compilation unit because of type mismatch)
b. offset of i is added
c. Value is referenced
Let's assume sizeof
id_token[0]
is2
byte and sizeof pointer toid_token[0]
is4
byte.Your later declaration may (mis)interprete the
id_tokens[0]
&id_tokens[1]
as an address and add some offset to it (which may be an existing or non-existing address, aligned or non-aligned address who knows).If it is your good day, program may crash or segfault immediately and you get a chance to fix the bug. If it is your bad day, program may just mess up with some other memory or communicate a wrong state to some module which can result in difficult to track bug and cause a nightmare.
Now I guess you understand why you got
(nil)
as output in Mr. 32's answer.这篇关于外部声明,T * V / S T []的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!