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:
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!
So the maximum size is between 2^30 and (2^31 - 1).
If you want to manually count it, the size of a struct is just the size of each of its data members after accounting for alignment. There's no magic overhead bytes for a struct.
You can check the size during compilation: static_assert (sizeof(mystruct) == 1024, "Size is not correct"); You need C++11 for that.
In 32 bit processor, it can access 4 bytes at a time which means word size is 4 bytes. Similarly in a 64 bit processor, it can access 8 bytes at a time which means word size is 8 bytes. Structure padding is used to save number of CPU cycles.
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.
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 struct
s 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
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With