c - 如何在堆栈上分配具有灵活数组成员的结构

标签 c flexible-array-member

假设我们有一个以灵活数组成员结尾的结构:

struct foo {
    size_t len;
    uint8_t data[];
};

如何在堆栈上分配这个结构(即内存在作用域结束时自动释放)?另外,如果 len 可以包含字段 data 的大小就好了。

目前,我做的事情是这样的:

uint8_t buf[256];
struct foo *foo = (struct foo *)buf;
foo->len = sizeof(buf) - sizeof(struct foo);

但是,它很容易出错。使用 alloca() 可能会稍微好一些:

struct foo *foo = alloca(256 + sizeof(struct foo));
foo->len = 256;

从那里,我可以定义一个这样的宏:

#define STACK_ALLOC_FOO(SIZE) ({                          \
    struct foo *_tmp = alloca(SIZE + sizeof(struct foo)); \
    _tmp->len = SIZE;                                     \
    _tmp;                                                 \
})

并声明它:

struct foo *foo = STACK_ALLOC_FOO(256);

但是,我不确定使用 alloca() 分配的内存的生命周期。是内部作用域还是函数?

另外,分配一个全局变量是行不通的(即使这不是我主要关心的)。

是否有人想好在堆栈上分配具有灵活数组成员的结构?

最佳答案

Let's say we have a struct ending with a Variable Length Array (VLA):

好吧,你不知道。您有一个以灵活数组成员 结尾的结构。不同的东西,主要用于动态内存分配场景。

How to allocate this struct on the stack

如果没有一些非标准的扩展,很难做到这一点。例如,保证返回没有有效类型 的内存的alloca 扩展。这意味着编译器尚未在内部将内存标记为某种类型。否则……

struct foo *foo = (struct foo *)buf;

你会得到严格的别名违规未定义行为,就像上面的错误代码一样。 What is the strict aliasing rule?

此外,您还需要注意对齐和填充。

However, I am not sure of lifetime of the memory allocated with alloca(). Is it the inner scope or the function?

可能吧。这不是一个标准函数,我不确定任何库是否为其行为提供了可移植的保证。它甚至不是 POSIX 函数。 Linux man 保证:

The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed when the function that called alloca() returns to its caller.

我假设这适用于 *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;

这里可以在本地定义bar256foobar256。您可以通过 foobar256f.datab.data 访问数据。这种类型的双关在 C 语言中是允许的并且定义明确。

在这一点上你可能会意识到这个结构只是更麻烦,它是值得的,并且只需要两个局部变量,一个是实际的 VLA:

size_t len = ... ;
uint8_t data[len];

关于c - 如何在堆栈上分配具有灵活数组成员的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68175878/

相关文章:

C 数据结构库

c - 零元素数组需要什么?

c - 替代灵活数组成员,无需动态内存分配

c - 在C中递归生成不重复的随机数

c - 更新结构中变量的值会导致同一结构中的另一个变量被修改

c++ - GCC 版本/标志和 FAM

c - 灵活数组成员中的严格别名?

c - 结构不工作,得到垃圾输出

c - 有没有办法在不使用 void 指针的情况下返回 C 函数中的任何类型?

c - 如何在 C 中以编程方式实现 'tee'?