我正在处理如下结构:
struct s1 {
struct s1 *next;
char a[64];
char b[64];
struct s2 *other;
};
struct s2 {
uint32_t x;
uint32_t y;
}
获得指向b
s1
的指针后,我尝试使用指针算法来访问s1->other
的成员。我尝试过以下方法:
// Assuming we have the following
struct s1 *p1 = ...
char *b = p1->b;
// Offset to get to s2
struct s2 *p2 = (struct s2*) b + 64;
// Access members
uint32_t result = p2->x;
我不认为填充是问题,因为我从b
开始。
答案 0 :(得分:5)
这一行:
struct s2 *p2 = (struct s2*) b + 64;
应更改为:
struct s2 *p2 = *(struct s2**) (b + 64);
添加了括号,因为强制转换的优先级高于+
。
使用双指针代替常规指针,因为正如@ M.M所说,b + 64
处的对象是struct s2 *
(不是struct s2
)。
我认为你只是为了练习而做。
你不应该在实际项目中使用这些技巧。如果你绝对必须,至少使用offsetof
来避免任何潜在的填充问题。
答案 1 :(得分:4)
正如@HolyBlackCat所指出的,显而易见的问题是+
- 运算符上的类型转换优先级,因此(struct s2*) b + 64
等同于(struct s2*) (b + 64*sizeof(struct s2))
。
无论如何,我会避免使用指针算术来获取下一个数据成员,因为可能存在填充问题,并且由于硬编码64
。 (编译器可以自由添加填充字节,因此你不能依赖64
,但我认为你知道这一点。)
我宁愿使用offsetof
来获取指向相应struct s1
所属的b
- 对象的指针,然后只需使用->other
来获取struct s2
{1}} - 指针:
struct s1 {
struct s1 *next;
char a[64];
char b[64];
struct s2 *other;
};
struct s2 {
uint32_t x;
uint32_t y;
};
int main() {
struct s2 os2 = { 10, 20 };
struct s1 os1 = { NULL, "asdf", "asdf", &os2 };
char *b = os1.b;
struct s1 *ps1 = (struct s1*)(b - offsetof(struct s1, b));
struct s2 *p2 = ps1->other;
// Access members
uint32_t result = p2->x;
return 0;
}
答案 2 :(得分:0)
你的问题在这里:
// Offset to get to s2
struct s2 *p2 = (struct s2*)b + 64; // Wrong!! casting b as a s2*
// you are getting the address of
// the 65tth element of an array of s2
// starting at b.
struct s2* p2 = (struct s2*)((char*)&(p1->b) + 64); // note the char* cast here.
// it will make this work even when b
// is not a char array