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?
答案 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)
假设:
SOME_OTHER_INT_VALUE
实际上适合int
然后是的。
答案 2 :(得分:0)
当您以这种方式访问结构字段时,您没有调用方法,因此不会返回任何内容(因此它不能作为副本)。
您真正要做的是直接访问您的结构字段,然后SomeStruct.someField
是当前结构的字段,您可以更改它和/或引用它。
在你的例子中
SomeStruct someStruct;
func(&(someStruct.someField));
,你正在做的是给你的结构领域一个指针,所以你可以随心所欲地做任何事情。