结构字段访问

时间:2013-09-09 20:10:09

标签: c++ struct

someStruct.someField的返回值是该字段的副本吗?如果我得到一个指向该值的指针,指针是指向结构中的值还是指向堆栈中的复制值?

e.g。是否有以下保证(它似乎在一个简单的测试中起作用)?

struct SomeStruct {
    int someField;
    SomeStruct() : someField(0) {}
}

void func(int* val) {
    *val = 42;
}

SomeStruct someStruct;
func(&(someStruct.someField));

// Is it guaranteed that someStruct.someField == 42?

3 个答案:

答案 0 :(得分:2)

似乎合法,见这里 -

How to pass a struct member as a pointer in a function

如果你想确定自己,你可以编译并查看汇编代码,你会看到编译器将直接地址传递给给定元素,而不会复制任何“out”它。

采取例如这段代码:

typedef struct {
    int a;
    int b;
    int c;
} T;

void set(int* c) {
    *c = 0;
}

int main()
{
    T t;
    set(&(t.b));
    set(&(t.c));

    return 0;
}

内置(使用gcc 4.2.2,-O2),并用objdump反汇编,主函数给出:

0000000000400500 <main>:
  400500:       53                      push   %rbx
  400501:       48 83 ec 10             sub    $0x10,%rsp     //"allocates" t on the stack
  400505:       48 8d 7c 24 04          lea    0x4(%rsp),%rdi //creates a direct pointer the t.b
  40050a:       e8 e1 ff ff ff          callq  4004f0 <set>
  40050f:       48 8d 7c 24 08          lea    0x8(%rsp),%rdi //creates a direct pointer the t.c
  400514:       e8 d7 ff ff ff          callq  4004f0 <set>
  400519:       8b 44 24 04             mov    0x4(%rsp),%eax
  40051d:       03 44 24 08             add    0x8(%rsp),%eax
  400521:       48 83 c4 10             add    $0x10,%rsp
  400525:       5b                      pop    %rbx
  400526:       c3                      retq

00000000004004f0 <set>:
  4004f0:       c7 07 00 00 00 00       movl   $0x0,(%rdi)
  4004f6:       c3                      retq

因此修改函数会直接写入定义的原始结构中,除非当然在创建它的副本的某个时刻(这是一个常见的错误,例如通过创建T t2 = t)

答案 1 :(得分:1)

假设:

  1. SOME_OTHER_INT_VALUE实际上适合int
  2. 编译器没有严重的错误。
  3. 然后是的。

答案 2 :(得分:0)

当您以这种方式访问​​结构字段时,您没有调用方法,因此不会返回任何内容(因此它不能作为副本)。

您真正要做的是直接访问您的结构字段,然后SomeStruct.someField是当前结构的字段,您可以更改它和/或引用它。

在你的例子中

SomeStruct someStruct;
func(&(someStruct.someField));

,你正在做的是给你的结构领域一个指针,所以你可以随心所欲地做任何事情。