C++ 直接访问结构成员
我有一个测试结构定义如下:C++ 直接访问结构成员,c++,memory,struct,C++,Memory,Struct,我有一个测试结构定义如下: 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 <<
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
test*t=新测试;//创建测试结构
int*ptr=(int*)t;
ptr[2]=15;//直接操纵第三个单词
cout c;//看看它是否真的影响了第三个整数
这在我的Windows上正常工作-按预期打印15张,但安全吗?我真的能确定变量在内存中是我想要的吗?特别是在这种组合结构的情况下(例如,f在我的编译器上是第五个字,但它是第六个变量)
如果没有,是否有其他方法可以直接操作结构成员而不在代码中实际使用struct->member构造?否您不能确定。编译器可以在结构成员之间自由引入填充 看起来你在问两个问题 将其作为3长度int-arrray进行治疗和测试是否安全? 可能最好避免这种情况。这可能是C++标准中定义的一个动作,但即使是,也不可能每个人都能理解你在这里做的事情。我认为,如果您阅读该标准,则不支持此操作,因为可能会填充结构,但我不确定 有没有更好的方法来访问没有名字的成员? 对。尝试使用宏/运算符。这将提供结构中特定构件的内存偏移量,并允许您将点正确定位到该构件
size_t offset = offsetof(mystruct,c);
int* pointerToC = (int*)((char*)&someTest + offset);
另一种方法是直接获取c的地址
int* pointerToC = &(someTest->c);
它可能不安全,100%不可读;因此,这类代码在实际生产代码中是不可接受的。您可能正在寻找
宏的偏移量。这将获得成员的字节偏移量。然后可以在该偏移处操纵杆件。但请注意,此宏是特定于实现的。包含<代码> STDDEF.H./C>以使其生效。< P>使用set方法和Booo::绑定来创建这个函数,将改变这个变量。 < P> >,在C++中另一个选项(不在C中)是创建指向成员对象的指针:
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
}
除了其他答案提出的填充/对齐问题外,您的代码违反了严格的别名规则,这意味着它可能会因优化构建而中断(不确定MSVC是如何做到这一点的,但GCC-O3
将因这种行为而中断)。本质上,由于test*t
和int*ptr
属于不同的类型,编译器可能会假定它们指向内存的不同部分,并且可能会对操作进行重新排序
考虑一下这个小小的修改:
test* t = new test;
int* ptr = (int*) t;
t->c = 13;
ptr[2] = 15;
cout << t->c;
test*t=新测试;
int*ptr=(int*)t;
t->c=13;
ptr[2]=15;
coutc;
最后的输出可以是13
或15
,具体取决于编译器使用的操作顺序。根据本标准第9.2.17段,如果结构是:
指向POD结构对象的指针,
使用
重新解释_cast,指向它的
初始成员(或如果该成员是
位字段,然后输入到
它驻留)反之亦然。[注:
因此,可能存在未命名的问题
POD结构对象中的填充,
但不是在它的开始,如果必要的话
以实现适当的对齐。]
但是,该标准对结构(甚至POD结构)的布局不作任何保证,除了后一个成员的地址将大于前一个成员的地址,前提是它们之间没有访问说明符(private:
、protected:
或public:
)。因此,将结构测试的初始部分作为3个整数的数组处理在技术上是未定义的行为。No-作为有效语句int*ptr=&(t->c)代码>显示,如果struct test(直接或间接)包含至少一个int.@MSalters,则int*可能会别名为test*。这没有意义&(t->c)具有int*类型,这与使用别名“窥视”结构不同。例如,如果(char*)&(t->c)-(char*)t不是sizeof(int)的倍数呢?非常感谢。不知道偏移量
!在过去的6年中,我一直把自己称为C++程序员。