Stack Danny
Stack Danny

Reputation: 8146

Finding the largest size of 100 structs at compile time in C

I have 100 structs that look something like this:

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;

I want to find the largest sizeof from among these structs at compile time. I tried using a comparison macro like this:

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

and then use that to construct the final define which will contain the result:

#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))) /*...*/ ))

However, the compiler runs out of space:

Error C1060 compiler is out of heap space

Which makes sense, given that this #define has to keep track of alot of numbers, since it simply replaces text. To be specific, the number of integers found in MAX_SIZEOF is exponential and can be described as:

number of numbers

where x is equal the number of structs involved. Assuming 4 bytes for an integer, the compiler would need to allocate 30.4 sextillion terabytes to compute this macro (if my calculations are correct). The maximum my system could handle was 17 structs (786430 numbers, 3.14 megabytes).

I am not sure how I can find an efficient solution in C.

In C++ I could achieve this with constexpr quite easily without any compiling issues whatsoever:

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))/*...*/)));

But yeah, I have to use C only here. ...Thanks for any ideas!

Upvotes: 7

Views: 1612

Answers (2)

Spektre
Spektre

Reputation: 51863

As I mentioned the other answer is way much nicer but as requested this works for me (on AtmelStudio 6.2 C compiler mode):

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);

The single line version is not working but if I divide the value into multiple lines (s_10,s_20,...) then I can use even 40 structs with correct output 99. Have not tried more as I am too lazy to copy paste others... I do not think its allocation problem you got there more like the max limit per line length of the preprocessor ...

The output value is s_size and can be also a #define ...

Upvotes: 1

Bodo
Bodo

Reputation: 9875

You can declare a union of all structs

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

and get the size of the union

sizeof(union allstructs)

When you want to transmit structures over the network you should also think about packing/padding of structures, byte order and floating point implementation.

Upvotes: 18

Related Questions