1

我有一个结构定义为:

typedef struct coro_context {
    int id;
    jmp_buf env;
    list_head list;
    jmp_buf waiter;
    long timeout;
    void *private;
    char stack[0];
} coro_context;

我需要用三个值初始化

  • 编号 = 0
  • 私有 = 函数指针
  • 在结构末尾追加一个合适的长度字符数组size

我目前的尝试看起来像(“ 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 可以),因为我需要在函数上下文之外使用这些初始化。

4

2 回答 2

1

我会使用一个联合覆盖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)

然后取 的地址.ctx。这也应该消除您的解决方案所存在的混叠问题。

您需要使用全局地址进行初始化,因为全局的值在静态初始化中不可用。

如果你想要 C99 兼容的东西,你将需要额外的标识符,但它不应该以两个下划线开头:

#include <setjmp.h>
typedef struct coro_context {
    int id;
    jmp_buf env;
    list_head list;
    jmp_buf waiter;
    long timeout;
    void *private;
    char stack[1]; /*c99 doesn't have flexible array members*/
} coro_context;

#define CORO_CONTEXT(name,size) \
    union { coro_context ctx; char buf[sizeof(coro_context)+size]; } name##_ctx__ = { { 0, {0},{0},{0}, 0, &name } }; \
    coro_context *name##_ctx = &name##_ctx__.ctx;

int my_name;

CORO_CONTEXT(my_name,32)
于 2018-08-19T12:20:54.473 回答
0

首先请注意,长缓冲区的大小可能与您的预期不符,因为它是四舍五入的。例如,如果 core_context 的大小为 10 字节,并且一个请求的额外大小为 3 字节,并且假设长大小为 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 );
于 2018-08-19T11:51:13.693 回答