我有一个结构定义为:
typedef struct coro_context {
int id;
jmp_buf env;
list_head list;
jmp_buf waiter;
long timeout;
void *private;
char stack[0];
} coro_context;
我需要用三个值初始化
size
的适当char数组我当前的尝试看起来像(“ unsigned long
”位是为了获得正确的对齐方式):
#define CORO_CONTEXT(name,size) \
unsigned long __##name##_ctx[(sizeof(coro_context)+size)/sizeof(unsigned long)]={0};\
coro_context *name##_ctx = (coro_context *)__##name##_ctx
这可行,但是有两个问题(好吧,问题是一个半;)):
private = name
的方法。注意:我坚持使用“静态初始化”,因为我想在普通的“ C”中使用它(如果需要,可以使用c11),因为我需要在函数上下文之外使用这些初始化。 / p>
答案 0 :(得分:1)
我会用一个用字符缓冲区覆盖0
实例的联合:
struct coro_context
,然后使用地址#include <setjmp.h>
typedef struct coro_context {
int id;
jmp_buf env;
list_head list;
jmp_buf waiter;
long timeout;
void *private;
char stack[]; /*should be [] in C11, [0] is not valid C */
} coro_context;
/*shouldn't start globals with underscore*/
/*shouldn't violate aliasing rules*/
/*C11 compound literals obviate the need for an extra global identifier*/
#define CORO_CONTEXT(name,size) \
coro_context *name##_ctx = &(union { coro_context ctx; char buf[sizeof(coro_context)+size]; }){ .ctx={ .private=&name } }.ctx;
int my_name;
CORO_CONTEXT(my_name,32)
。这也应该摆脱您的解决方案所遇到的别名问题。
您需要使用全局地址进行初始化,因为全局值在静态初始化中不可用。
如果您希望与C99兼容,则需要额外的标识符,但它不能以两个下划线开头:
.ctx
答案 1 :(得分:0)
首先请注意,长缓冲区的大小可能会四舍五入,因此可能与您的预期不符。例如,如果core_context的大小为10个字节,并且其中一个请求额外的大小为3个字节,并且假设long的大小为8个字节。您得到(10 + 3)/ 8 = 1,因此您分配了1个long来处理13个字节(而不是分配2个long)。
所以而不是
unsigned long __##name##_ctx[(sizeof(coro_context)+size)/sizeof(unsigned long)]={0};
我认为应该是
unsigned long __##name##_ctx[(sizeof(coro_context)+size+sizeof(unsigned long))/sizeof(unsigned long)]={0};
现在有关静态初始化,我不会使用长缓冲区,而是创建一个具有相同的前n个变量,并在最后请求大小的缓冲区的新结构。可以静态初始化此结构,并且所请求的指针将指向它。所以代码看起来像这样:
#define CORO_CONTEXT(name,size,my_private_method) \
typedef struct coro_context##_name {\
int id;\
jmp_buf env;\
list_head list;\
jmp_buf waiter;\
long timeout;\
void *private;\
char stack[0];\
char additional_buffer[size];\
} coro_context##name;\
coro_context##name __name##_ctx = {0,0,0,0,0,my_private_method};\
coro_context *name##_ctx = (coro_context *)&__name##_ctx
为简单起见,您还可以使用简化的结构,并使用coro_context结构作为包装器结构的“基础”(即,使用单个变量而不是声明所有coro_context变量)来检查此代码:
typedef struct coro_context {
int id;
void *private;
} coro_context;
#define DECLARE_CORO_CONTEXT(size,private_method)\
typedef struct wrapper_for_core_context\
{\
coro_context base;\
char buffer[size];\
}wrapper;\
wrapper my_wrapper = { {0, private_method}, 0 };\
coro_context *cc = (coro_context *)&my_wrapper;
//now the using code
DECLARE_CORO_CONTEXT( 20, test_at_avro_bytes_field_all_data_values );