我有以下头文件:
struct StackList_s;typedef struct StackList_s StackList_t;//从这里我添加了方法签名以下源文件:
struct StackList_s{ …
你可以通过使用#define而不使用VLA来做类似于Artyer的回答
标题:
#define STACKLISTSIZE 32 typedef uint8_t stl_storage[STACKLISTSIZE]; typedef struct stacklist_s stacklist_t; stacklist_t* stl_create_from_stack(stl_storage b); //user provides memory stacklist_t* stl_allocate(void); //library allocates memory, user must free.
资源:
int myfunction() { stl_storage x; stacklist_t* sp = stl_create_from_stack(x); //do something with sp. }
确保你有一个编译时断言 sizeof(stack_s) == STACKSTRUCTSIZE 在实现文件中。
sizeof(stack_s) == STACKSTRUCTSIZE
某些实现保证编译单元之间的调用将以与平台的应用程序二进制接口(ABI)一致的方式处理,而不考虑被调用函数将对其接收的地址或调用者将执行的操作执行的操作。存储其提供的地址,或者一旦函数返回就会执行此类存储。在这样的实现上,给出如下内容:
// In header typedef union FOO_PUBLIC_UNION { uint64_t dat[4]; // Allocate space double dummy_align1; // Force alignment void *dummy_align2; // Force alignment } FOO; void act_on_foo(FOO_PUBLIC_UNION*); // In code FOO x = {0}; act_on_foo(&x);
在一个编译单元中,类似于:
struct FOO_PRIVATE { int this; float that; double whatever; }; typedef union FOO_PUBLIC_UNION { uint64_t dat[4]; struct FOO_PRIVATE priv; } FOOPP; void act_on_foo(FOO *p) { FOOPP *pp = (FOOPP*)p; pp->priv.whatever = 1234.567; }
只要大小 FOO 和 FOOPP 匹配,从第一个编译单元调用外部函数的行为将被定义为分配 sizeof(FOO) 字节,将它们归零,并将它们的地址传递给 act_on_foo ,然后将其行为定义为对其接收地址的字节进行操作,而不考虑它们如何获取其值或稍后调用者将如何处理它们。
FOO
FOOPP
sizeof(FOO)
act_on_foo
不幸的是,即使几乎每个实现都应该能够产生与调用它一无所知的函数一致的行为,但是没有标准的方法向编译器指示特定的函数调用应该被视为“不透明”。旨在用于有用目的的实现可以并且通常使用“普通”函数调用来支持这样的语义,无论标准是否需要,并且这样的语义对于仅用于它们不会有用的目的的实现几乎没有价值。 。不幸的是,这导致了一个Catch 22:没有理由要求标准强制要求实现在有或没有授权的情况下可以自由执行,如果它们有用,但是一些编译器编写者认为标准缺乏任务是鼓励拒绝支持。
您 能够 使用VLA或 alloca 在Linux中:
alloca
图书馆标题:
struct StackList_s; typedef struct StackList_s StackList_t; extern const size_t StackList_size; // If you're using VLAs extern const size_t StackList_align; StackList_t* stl_init_inline(char stack_source[], ...);
图书馆来源:
#include "header.h" struct StackList_s { // ... }; const size_t StackList_size = sizeof(StackList_t); // If you're using VLAs #include <stdalign.h> #include <stdint.h> const size_t StackList_align = alignof(StackList_t); StackList_t* stl_init_inline(char stack_source[], ...) { // align the address to the nearest multiple of StackList_align uintptr_t address = (uintptr_t) ((void*) stack_source); if (address % StackList_align != 0) { address += StackList_align - address % StackList_align; } StackList_t* stack = (StackList_t*) ((void*) address); stl_init(stack, ...); return stack; }
主要来源
#include <header.h> StackList_t* stack = alloca(Stacklist_size); stl_init(stack, ...); char stack_source[StackList_size + StackList_align - 1]; // Not compile time. StackList_t* stack = stl_init_inline(stack_source, ...);
这个 将 将它分配到堆栈上,你不需要释放它,但它比它更慢,更冗长 StackList_t stack_source; 。 (和 alloca 仅限Linux)
StackList_t stack_source;
对于第二个问题,您需要一个结构的完整定义来获得它的大小。常见的陷阱包括这样的事实 sizeof(struct { int a; }) == sizeof(struct { int a; }) 可能是假的。它可能不会,所以你可以这样做 #define StackList_size sizeof(struct { integer_t count; struct StackListNode_s *top; integer_t version_id; }) 但这也导致了大量的代码重复。
sizeof(struct { int a; }) == sizeof(struct { int a; })
#define StackList_size sizeof(struct { integer_t count; struct StackListNode_s *top; integer_t version_id; })
我个人只是将结构定义放在头文件中,只是在某处的注释中声明“不要弄乱成员或我的方法不起作用”(也许让名字开始于 _ 暗示他们是私人的)
_