我刚刚阅读Extending a struct in C,我似乎不明白代码的某些部分是做什么的。
这是他目前的代码:
typedef struct A {
int x;
}A;
typedef struct B {
A a;
int d;
}B;
void fn(){
B *b;
((A*)b)->x = 10;
}
我想知道,((A*)b)->x = 10;
与b->a.x = 10;
如何相同?
你如何解释这行代码?
修改
(A*)
和(A*)b
做了什么?
答案 0 :(得分:3)
根据标准,指向结构的指针必须等于指向该结构的初始成员的指针。换句话说,在其专用于存储struct B
内容的区域前面的struct A
中不得插入填充。这就是演员阵容有效的原因:
第6.7.2.1.13节
在结构对象中,非位字段成员和位域所在的单元具有按声明顺序增加的地址。指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。结构对象中可能有未命名的填充,但不是在其开头
答案 1 :(得分:2)
尝试可视化struct B
如何存储在内存中,您将理解为什么它们是平等的。
struct B
放置为a
,结构A
后面跟着成员d
。
现在,当您查看((A*)b)
时,它是str B
转换为struct A
,其内存中的成员x
为零偏移。
下面是典型内存布局中的struct B
,
+--------------+
| | |
| A | d |
| | |
+--------------+
现在如果你再扩展一下,
+--------------+
| | |
| x | d |
| | |
+--------------+
答案 2 :(得分:2)
如果检查结构A
的内存布局,它看起来像这样
+---+ | x | +---+
如果你将它与B
的内存布局进行比较,它看起来像这样:
+---+---+ | x | d | +---+---+
当你看到它时,更容易看出它为什么会起作用。