[注:这是从https://softwareengineering.stackexchange.com/q/369604/126197转发的,由于某些原因,这个问题立即被否决了。两次。显然,这里还有更多的爱!]
下面是一个供应商示例中的一些代码转述。
我已经查找过关于按值传递堆栈分配结构的权威文档,但还没有找到确切的单词。简单地说: C99能保证这是安全的吗?
typedef struct {
int32_t upper;
int32_t lower;
} boundaries_t;
static boundaries_t calibrate() {
boundaries_t boundaries; // struct allocated on stack
boundaries.upper = getUpper();
boundaries.lower = getLower();
return boundaries; // return struct by value
}
int main() {
boundaries_t b;
b = calibrate();
// do stuff with b
...
}注意,calibrate()在堆栈上分配boundaries结构,然后按值返回。
如果编译器能够保证calibrate()的堆栈帧在分配给b时是完整的,那么一切都很好。也许这就是C99的按价值传递合同的一部分?
(上下文:我的世界是嵌入式系统,很少能看到按值传递的系统。)我确实知道,从堆栈分配的结构中返回指针是一种灾难,但这种按值传递的东西感觉很陌生。)
发布于 2018-04-18 22:21:17
是的,非常安全。当您按值返回时,它会将结构的成员复制到调用者的结构中。只要结构不包含指向本地对象的任何指针,它就是有效的。
返回结构通常是不常见的,因为如果它们很大,就需要大量的复制。但有时,我们将数组放入结构中,以便与其他数据类型一样,通过值传递数组(数组在用作参数或返回值时通常会衰减到指针)。
原件增编
(我相信巴玛尔不会介意.)
正如@DanielH所指出的,在SysV ABI用于amd64的情况下,编译器将为按值返回结构做准备。如果它很小,整个结构可以在寄存器中返回(读: fast)。如果它更大,编译器将在调用方的堆栈帧中分配空间,并传递一个指向被调用方的指针。然后被调用者在返回时将结构的值复制到结构值中。从医生那里:
如果类型具有类内存,则调用方为返回值提供空间,并将此存储的地址在%rdi中传递,就好像它是函数的第一个参数一样。实际上,这个地址变成了一个“隐藏”的第一个参数。
发布于 2018-04-18 22:21:47
b = calibrate();
// do stuff with b表现得很好。
boundaries_t只包含作为成员的整型。通过值传递它并在函数调用中使用分配给它的对象是完全安全的。
发布于 2018-04-18 22:32:24
https://stackoverflow.com/questions/49909801
复制相似问题