struct和sizeof的数组

Les*_*sto 5 c pointers structure void-pointers

我想用C语言编写(没有特别的味道,比方说c11)一个通用的全局const数组结构,如下面的伪代码:

void * generic[] ={&(struct a va),&(struct b vb)};
Run Code Online (Sandbox Code Playgroud)

现在我想创建一个函数,给定所需结构的位置的id(我打算为每个id使用const,硬编码),将复制它.

因为那copy()也是通用的(接受一个void *目的地),它需要知道严格的大小,可能由调用者指定(很多容易出错,他已经需要提供目标结构和正确的id)或者我也会sizeof为每个结构维护一个正确的并行数组.

有没有办法在编译时自动化sizeof数组的初始化?或者甚至实现某种技巧让用户指定只是将指针传递给没有id的struct,而不必编写专门的get_struct_x()

不允许动态分配(alloc(),局部变量很好),所有struct和generic数组内容在编译时都是已知的.

对不起我的错误解释,随时改进/纠正它.

编辑以澄清:我需要从存储了许多结构类型的数组深层复制已知的结构类型,但相同的类型永远不会重复.我需要从一个通用的get函数中执行它将从不同的线程调用,因此在复制之前和之后将锁定一个互斥锁,并且我希望将所有锁定和转换代码保存在一个点上,以最小化调试和创建更有效的测试.

Les*_*sto 1

我的一个没有 stackoverflow 帐户的朋友(@Francesco)重新阐述了 @WhozCraig 的答案,添加了(非常旧的)X 宏(感谢Randy Meyers 的精彩文章)来构建通用结构数组并且枚举有助于访问数组的结构,使用户只能编辑一个位置;

回去工作时我告诉他我想尝试制作特定的结构吸气剂(因为数组中不会有重复的结构类型。如果你弄错了,编译时错误,所以在一天结束时开发时你会低头,但一旦编译它就会更健壮),所以我们会对请求的结构体的类型进行编译检查;回到家他就已经实施了。荣誉!

然后,我又在这方面浪费了一些时间,并让开发人员只需输入一次结构,以防止那一侧出现错位;这是优化螺旋的开始;

  • 由于专门的 get 和 put,不再需要 size 数组,因此删除了通用结构
  • 不需要初始化结构,我们使用“匿名”结构初始化
  • 因为“匿名”初始化,直接访问结构体比较困难
  • 直接访问需要系统知识,从而提高认识
  • 使其代码更具可读性
  • 易于在外部独立文件上导出GENERIC_TABLE和结构定义
  • #ifdef onGENERIC_TABLE工作正常,将其移至外部标头以增加可读性
  • 局部变量外部不需要动态初始化(无垃圾,嵌入式友好)
  • 非常容易使用

成本

  • 也许预处理器有点臃肿?
  • 看起来很多 OOP xD
  • 您可以使用未启动的指针调用 get 和 put

TL;DR:这里是完整的编译代码和基本示例:

#include <memory.h>
#include <stdio.h>
#include <stdlib.h>

/* BEGIN: just some struct to test, fell free to move them on external header file */
struct A
{
    int a1;
    long a2;
};

struct B
{
    float b1;
    char b2[6];
};

struct C
{
    unsigned int c1;
    double c2[5];
};
/* END: just some struct to test, fell free to move them on external header file */

/* this macro will create the right X macro element, and also initiliaze the "anonymous" struct */
#define ADD_STRUCT_TO_ARRAY(xu) X(xu, &(struct xu){})SEP

/* BEGIN: add or remove your own struct here! 
 * fell free to move them on external header file 
 * just need to pass struct name without "struct" to ADD_STRUCT_TO_ARRAY macro */
#define GENERIC_TABLE \
    ADD_STRUCT_TO_ARRAY(A) \
    ADD_STRUCT_TO_ARRAY(B) \
    ADD_STRUCT_TO_ARRAY(C)
/* END: add or remove your own struct here! */

/* here we initialize the enum, where the type of the struct is the key, and its position in the array the value */
#define SEP ,
#define X(a,b) a
enum STRUCT {
    GENERIC_TABLE
};
#undef X

/* here we initalize the array of pointer to the structure */
#define X(a,b) b
void * const generic[] =
{
    GENERIC_TABLE
};
#undef X
#undef SEP

/* here we create all the getter function. add here your array locking code */
#define SEP ;
#define X(a,b) void get_##a(struct a * dest){memcpy(dest, generic[a], sizeof(struct a) );} 
GENERIC_TABLE
#undef X
#undef SEP

/* here we create all the putter function. add here your array locking code */
#define SEP ;
#define X(a,b) void put_##a(struct a * source){memcpy(generic[a], source, sizeof(struct a) );}
GENERIC_TABLE
#undef X
#undef SEP

/*run, code, run!*/
int main()
{
    struct A a_copy;
    struct B b_copy;
    struct C c_copy;

    get_A(&a_copy);
    get_B(&b_copy);
    get_C(&c_copy);

    printf("STRUCTURE IN ARRAY BEFORE INITIALIZATION\n");
    printf("A = %d\n", a_copy.a1);
    printf("B = %f\n", b_copy.b1);
    printf("C = %x\n", c_copy.c1);

    a_copy.a1 = -1;
    b_copy.b1 = 2.3;
    c_copy.c1 = 3;

    printf("STRUCTURE CHANGED TO\n");
    printf("A = %d\n", a_copy.a1);
    printf("B = %f\n", b_copy.b1);
    printf("C = %x\n", c_copy.c1);

    printf("STRUCTURE SAVED\n");
    put_A(&a_copy);
    put_B(&b_copy);
    put_C(&c_copy);

    get_A(&a_copy);
    get_B(&b_copy);
    get_C(&c_copy);

    printf("STRUCTURE LOADED\n");
    printf("A = %d\n", a_copy.a1);
    printf("B = %f\n", b_copy.b1);
    printf("C = %x\n", c_copy.c1);

    a_copy.a1 = 1000;
    b_copy.b1 = -50.576;
    c_copy.c1 = 700;

    printf("STRUCTURE CHANGED TO\n");
    printf("A = %d\n", a_copy.a1);
    printf("B = %f\n", b_copy.b1);
    printf("C = %x\n", c_copy.c1);

    get_A(&a_copy);
    get_B(&b_copy);
    get_C(&c_copy);

    printf("STRUCTURE RELOADED WITHOUT SAVING\n");
    printf("A = %d\n", a_copy.a1);
    printf("B = %f\n", b_copy.b1);
    printf("C = %x\n", c_copy.c1);


    return 0;
}
Run Code Online (Sandbox Code Playgroud)