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++程序员。