繁体   English   中英

直接访问结构成员

[英]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 *tint *ptr是不同的类型,编译器可能会假设它们指向 memory 的不同部分,并且它可能会重新排序操作。

考虑这个小修改:

test* t = new test;
int* ptr = (int*) t;

t->c = 13;
ptr[2] = 15;
cout << t->c;

最后的 output 可以是1315 ,具体取决于编译器使用的操作顺序。

根据标准的第 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM