假设我们有一个以可变长度数组 (VLA) 结尾的结构:
好吧,你不知道。你有一个以 a 结尾的结构灵活的阵列成员。不同的东西,主要用于动态内存分配场景。
如何在堆栈上分配该结构
如果没有一些非标准扩展,很难做到这一点。例如一个alloca
保证返回没有内存的扩展有效型。这意味着编译器尚未在内部将内存标记为具有某种类型。否则...
结构 foo *foo = (结构 foo *)buf;
您会得到严格的别名违规未定义行为,就像上面的错误代码一样。严格的别名规则是什么? https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
此外,您还需要注意对齐和填充。
但是,我不确定用 alloca() 分配的内存的生命周期。是内部作用域还是函数?
是的,可能是。它不是一个标准函数,我不确定是否有任何库对其行为提供了可移植的保证。它甚至不是 POSIX 函数。 Linuxman
保证:
alloca() 函数在调用者的堆栈帧中分配 size 字节的空间。当调用 alloca() 的函数返回到其调用者时,该临时空间会自动释放。
我假设这适用于 *nix 下的 gcc/glibc,但不适用于其他工具链或系统。
为了获得可移植且坚固的代码,您可以做的是这样的:
struct foo {
size_t len;
uint8_t data[];
};
struct bar256 {
size_t len;
uint8_t data[256];
};
typedef union
{
struct foo f;
struct bar256 b;
} foobar256;
Here bar256
and foobar256
可以在本地定义。您可以通过以下方式访问数据f.data
or b.data
of a foobar256
。这种类型双关在 C 中是允许的并且是明确定义的。
此时,您可能会意识到该结构只是更麻烦,值得,只需使用两个局部变量,其中一个是实际的 VLA:
size_t len = ... ;
uint8_t data[len];