如果我们在结构体中有指向该结构体其他成员的指针,是否可以保证如果我们从函数返回结构体时,这些指针仍将指向该结构体的内部成员?
例如,这个经过小型优化的缓冲区结构:
#include <stdint.h>
#include <stdio.h>
struct buffer {
uint8_t *begin;
uint8_t *end;
uint8_t sso[20];
};
struct buffer test() {
struct buffer buffer;
buffer.begin = buffer.sso;
buffer.end = buffer.begin + 20;
return buffer;
}
int main(void) {
struct buffer buffer = test();
return buffer.begin == buffer.sso ? 0 : 1;
}
当我在本地编译此代码并运行它时,它返回0,因此buffer.begin
仍指向buffer.sso
的开头。但是,是否可以保证总是这样?还是取决于编译器特定的RVO行为?
答案 0 :(得分:3)
不。函数返回时,buffer
中test()
后面的内存将不再存在。函数返回后,指向此buffer
以及指向该buffer
中任何成员的所有指针均无效。
以下是有效的替代方法:
#include <stdint.h>
#include <stdio.h>
struct buffer {
uint8_t *begin;
uint8_t *end;
uint8_t sso[20];
};
void buffer_init(struct buffer *buffer) {
buffer->begin = buffer->sso;
buffer->end = buffer->begin + 20;
}
int main(void) {
struct buffer buffer;
buffer_init(&buffer);
return buffer.begin == buffer.sso ? 0 : 1;
}
答案 1 :(得分:0)
它不起作用,因为分配了局部变量buffer
的内存超出范围,但是指针仍指向该区域。在main()中分配的buffer
将具有不同的地址。该结构的内容是从函数中复制的,因此您必须更新指针。
一个高级版本是不使用指针,但使用数组索引的版本:
struct buffer {
size_t begin;
size_t end;
uint8_t sso[20];
};
struct buffer test() {
struct buffer buffer;
buffer.begin = 0;
buffer.end = 20;
return buffer;
}
您可以安全地从函数中返回该代码,并且一切仍然有效。