【问题标题】:Finding the largest size of 100 structs at compile time in C在 C 中编译时查找 100 个结构的最大大小
【发布时间】:2019-05-09 02:52:51
【问题描述】:

我有 100 个看起来像这样的结构:

struct s00 { char   data[30]; };
struct s01 { char   data[30]; };
struct s02 { int    data[10]; };
struct s03 { double data[5];  };
struct s04 { float  data[20]; };
struct s05 { short  data[15]; };
struct s06 { char   data[7];  };
struct s07 { int    data[19]; };
struct s08 { double data[11]; };
struct s09 { float  data[5];  };
struct s10 { char   data[52]; };
//...
struct s99 { char   data[12]; };

typedef struct s00 s00;
typedef struct s01 s01;
typedef struct s02 s02;
//...
typedef struct s99 s99;

我想在编译时从这些结构中找到最大的sizeof。我尝试使用这样的比较宏:

 #define LARGER(a, b) ((a) > (b) ? (a) : (b))

然后使用它来构造包含结果的最终定义:

#define MAX_SIZEOF (LARGER(sizeof(s00), \
                    LARGER(sizeof(s01), \
                    LARGER(sizeof(s02), \
                    LARGER(sizeof(s03), \
                    LARGER(sizeof(s04), \
                    LARGER(sizeof(s05), \
                    LARGER(sizeof(s06), \
                    LARGER(sizeof(s07), \
                    LARGER(sizeof(s08), \
                    LARGER(sizeof(s09), \
                    LARGER(sizeof(s10), \
                    //...
                    sizeof(s99))) /*...*/ ))

但是,编译器空间不足:

错误 C1060 编译器堆空间不足

这是有道理的,因为 #define 必须跟踪很多数字,因为它只是替换文本。具体来说,MAX_SIZEOF 中的整数个数是指数级的,可以描述为:

其中 x 等于所涉及的结构的数量。假设一个整数有 4 个字节,编译器需要分配 30.4 兆兆兆字节来计算这个宏(如果我的计算是正确的)。我的系统最多可以处理 17 个结构(786430 个数字,3.14 兆字节)。

我不确定如何在 C 中找到有效的解决方案。

在 C++ 中,我可以使用 constexpr 轻松实现这一点,而不会出现任何编译问题:

constexpr size_t LARGER(size_t a, size_t b) {
    return a > b ? a : b;
}
constexpr size_t MAX_SIZEOF() {
return 
    LARGER(sizeof(s00), \
    LARGER(sizeof(s01), \
    LARGER(sizeof(s02), \
    LARGER(sizeof(s03), \
    LARGER(sizeof(s04), \
    LARGER(sizeof(s05), \
    LARGER(sizeof(s06), \
    LARGER(sizeof(s07), \
    LARGER(sizeof(s08), \
    LARGER(sizeof(s09), \
    LARGER(sizeof(s10), \
    //...
    sizeof(s99))/*...*/)));

但是,我只能在这里使用 C。 ...感谢您的任何想法!

【问题讨论】:

  • 你为什么要这样做?
  • @Edition 我正在通过套接字(CSFML UDP 套接字)发送许多不同的结构。由于这些套接字接收固定大小的缓冲区,我想找到最大值,以便缓冲区不会超出范围。我通过简单地动态分配缓冲区来避免这个问题,但我现在想提高程序的性能。
  • c++ 如何实现constexpr,它会在编译时评估您在c 中尝试的内容,而不用尖叫?
  • @user2162550 好吧,我想编译器确实在评估每个三元运算符,而不是在处理层时替换文本。
  • 或者更确切地说;预处理器正在评估它。

标签: c algorithm macros preprocessor


【解决方案1】:

你可以声明所有结构的联合

union allstructs {
    struct s00 s00val;
    struct s01 s01val;
    /* ... */
    struct s99 s99val;
}

得到联合体的大小

sizeof(union allstructs)

当您想通过网络传输结构时,您还应该考虑结构的打包/填充、字节顺序和浮点实现。

【讨论】:

  • 我本来打算使用max() 宏语句,但这更好......所以+1
  • @Spektre 我仍然很想知道它是如何工作的
  • @StackDanny 我将该方法添加为答案
【解决方案2】:

正如我提到的,另一个答案要好得多,但根据要求,这对我有用(在 AtmelStudio 6.2 C 编译器模式下):

typedef struct { char   data[30]; }s00;
typedef struct { char   data[30]; }s01;
typedef struct { int    data[10]; }s02;
typedef struct { double data[5];  }s03;
typedef struct { float  data[20]; }s04;
typedef struct { short  data[15]; }s05;
typedef struct { char   data[7];  }s06;
typedef struct { int    data[19]; }s07;
typedef struct { double data[11]; }s08;
typedef struct { float  data[5];  }s09;
typedef struct { char   data[5]; }s10;
typedef struct { char   data[5]; }s11;
typedef struct { char   data[5]; }s12;
typedef struct { char   data[5]; }s13;
typedef struct { char   data[5]; }s14;
typedef struct { char   data[5]; }s15;
typedef struct { char   data[2]; }s16;
typedef struct { char   data[5]; }s17;
typedef struct { char   data[5]; }s18;
typedef struct { char   data[5]; }s19;
typedef struct { char   data[3]; }s20;
typedef struct { char   data[5]; }s21;
typedef struct { char   data[5]; }s22;
typedef struct { char   data[5]; }s23;
typedef struct { char   data[5]; }s24;
typedef struct { char   data[5]; }s25;
typedef struct { char   data[5]; }s26;
typedef struct { char   data[4]; }s27;
typedef struct { char   data[5]; }s28;
typedef struct { char   data[5]; }s29;
typedef struct { char   data[5]; }s30;
typedef struct { char   data[5]; }s31;
typedef struct { char   data[5]; }s32;
typedef struct { char   data[5]; }s33;
typedef struct { char   data[5]; }s34;
typedef struct { char   data[5]; }s35;
typedef struct { char   data[5]; }s36;
typedef struct { char   data[5]; }s37;
typedef struct { char   data[5]; }s38;
typedef struct { char   data[99];}s39;

#define sm(a0,a1) (sizeof(a0)>sizeof(a1)?sizeof(a0):sizeof(a1))
#define mm(a0,a1) (a0>a1?a0:a1)
#define s_10 sm(sm(sm(sm(sm(sm(sm(sm(sm(s00,s01),s02),s03),s04),s05),s06),s07),s08),s09)
#define s_20 sm(sm(sm(sm(sm(sm(sm(sm(sm(s10,s11),s12),s13),s14),s15),s16),s17),s18),s19)
#define s_30 sm(sm(sm(sm(sm(sm(sm(sm(sm(s20,s21),s22),s23),s24),s25),s26),s27),s28),s29)
#define s_40 sm(sm(sm(sm(sm(sm(sm(sm(sm(s30,s31),s32),s33),s34),s35),s36),s37),s38),s39)
const int s_size=mm(mm(mm(s_10,s_20),s_30),s_40);

单行版本不起作用,但如果我将值分成多行(s_10,s_20,...),那么我甚至可以使用 40 个structs 并正确输出99。没有尝试更多,因为我懒得复制粘贴其他人...我不认为您到达那里的分配问题更像是预处理器的每行长度的最大限制...

输出值为s_size,也可以是#define...

【讨论】:

  • 感谢提交!是的,拆分是个好主意~
猜你喜欢
  • 2011-11-15
  • 2013-10-24
  • 2017-05-30
  • 2018-01-08
  • 2016-06-18
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 2012-12-15
相关资源
最近更新 更多