1

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

例如以下是否保证(它似乎在一个简单的测试中工作)工作?

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?
4

3 回答 3

2

似乎合法,请参见此处-

如何将结构成员作为指针传递给函数

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

例如这段代码:

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)

于 2013-09-09T20:38:26.543 回答
1

假如说:

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

好的。

于 2013-09-09T20:24:12.040 回答
0

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

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

在你的例子中

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

,你正在做的是给你的结构字段的指针,所以你可以用它做任何你想做的事情。

于 2013-09-09T21:09:22.370 回答