【发布时间】:2016-09-21 15:02:12
【问题描述】:
假设我有一个结构并将偏移量提取到一个成员:
struct A {
int x;
};
size_t xoff = offsetof(A, x);
如果给定指向struct A 的指针,我该如何以符合标准的方式提取成员?当然假设我们有一个正确的struct A* 和一个正确的偏移量。一种尝试是:
int getint(struct A* base, size_t off) {
return *(int*)((char*)base + off);
}
这可能会起作用,但请注意,例如,如果指针是同一数组的指针(或末尾的指针),则指针算术似乎仅在标准中定义,这不一定是这种情况。因此从技术上讲,该构造似乎依赖于未定义的行为。
另一种方法是
int getint(struct A* base, size_t off) {
return *(int*)((uintptr_t)base + off);
}
这也可能会起作用,但请注意 intptr_t 不需要存在,据我所知 intptr_t 上的算术不需要产生正确的结果(例如,我记得一些 CPU 有能力处理非字节对齐的地址,这表明intptr_t 在数组中的每个char 以8 的步长增加)。
看起来标准中忘记了一些东西(或者我错过了一些东西)。
【问题讨论】:
-
我很确定别名为
char*和指向同一个对象(不一定是数组)的指针都是有效的。等待权威答案。 -
(char *)base可用于在base内的任意位置移动(并且超过末尾)。任何对象的行为都类似于大小为 1 的数组。 -
return *(int*)((char*)base + off);很容易失败,因为int访问可能未对齐。例如。int访问可能会导致奇地址上的总线故障。 OTOH OP 确实说过“假设......我们有一个正确的结构 A* 和一个正确的偏移量” -
最好访问具有该字段类型或
unsigned char(无陷阱,无填充)的字段。 -
不清楚为什么代码不使用
A->x来访问该字段。A->x没有提供的你该怎么做?如果所有代码都是A并且到字段x的偏移量,则缺少字段类型/大小会阻止以一致的方式访问。
标签: c pointers language-lawyer offsetof