[英]Accessing struct members directly
我有一个测试结构定义如下:
struct test{
int a, b, c;
bool d, e;
int f;
long g, h;
};
在某处我以这种方式使用它:
test* t = new test; // create the testing struct
int* ptr = (int*) t;
ptr[2] = 15; // directly manipulate the third word
cout << t->c; // look if it really affected the third integer
这在我的 Windows 上正常工作 - 它按预期打印 15,但它安全吗? 我真的可以确定变量在 memory 中吗?
如果没有,是否有任何其他方法可以直接操作 struct 成员,而无需在代码中实际使用 struct->member 构造?
看起来你在问两个问题
将 &test 视为 3 长度的 int 数组是否安全?
最好避免这种情况。 这可能是 C++ 标准中定义的操作,但即使是这样,与您一起工作的每个人都不太可能理解您在此做什么。 我相信如果您阅读标准,因为可能填充结构,这不受支持,但我不确定。
有没有更好的方法来访问没有名字的成员?
是的。 尝试使用offsetof宏/运算符。 这将提供结构中特定成员的 memory 偏移量,并允许您正确 position 指向该成员。
size_t offset = offsetof(mystruct,c);
int* pointerToC = (int*)((char*)&someTest + offset);
另一种方法是直接获取 c 的地址
int* pointerToC = &(someTest->c);
不,你不能确定。 编译器可以自由地在结构成员之间引入填充。
要添加到JaredPar 的答案,仅 C++ 中的另一个选项(不在纯 C 中)是创建指向成员 object 的指针:
struct test
{
int a, b, c;
bool d, e;
int f;
long g, h;
};
int main(void)
{
test t1, t2;
int test::*p; // declare p as pointing to an int member of test
p = &test::c; // p now points to 'c', but it's not associating with an object
t1->*p = 3; // sets t1.c to 3
t2->*p = 4; // sets t2.c to 4
p = &test::f;
t1->*p = 5; // sets t1.f to 5
t2->*p = 6; // sets t2.f to 6
}
您可能正在寻找offsetof
宏。 这将为您提供成员的字节偏移量。 然后,您可以在该偏移处操作成员。 但请注意,此宏是特定于实现的。 包括stddef.h
以使其工作。
它可能不安全并且 100% 不可读; 从而使这种代码在现实生活中的生产代码中不可接受。
使用 set 方法和 boost::bind 创建函子,这将改变这个变量。
除了填充/对齐问题之外,其他答案已经提出,您的代码违反了严格的别名规则,这意味着它可能会因优化构建而中断(不确定 MSVC 是如何做到这一点的,但 GCC -O3
会在这种类型的行为上中断)。 本质上,因为test *t
和int *ptr
是不同的类型,编译器可能会假设它们指向 memory 的不同部分,并且它可能会重新排序操作。
考虑这个小修改:
test* t = new test;
int* ptr = (int*) t;
t->c = 13;
ptr[2] = 15;
cout << t->c;
最后的 output 可以是13
或15
,具体取决于编译器使用的操作顺序。
根据标准的第 9.2.17 段,实际上将指向结构的指针转换为指向其第一个成员的指针是合法的,前提是该结构是POD :
指向 POD 结构 object 的指针,使用 reinterpret_cast 适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。 [注意:因此,在 POD 结构 object 中可能存在未命名的填充,但不是在其开头,这是实现适当 alignment 所必需的。 ]
但是,该标准不保证结构的布局——即使是 POD 结构——除了后面成员的地址将大于前面成员的地址,前提是没有访问说明符( private:
, protected:
或public:
) 他们之间。 因此,将struct test
的初始部分视为 3 个整数的数组在技术上是未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.