A typical compiler will determine structure alignment requirements from the most strict alignment requirement among the struct members. Bit-fields are typically treated as ordinary fields in that process.
That means since your first structure contains a member of type int
(which, apparently, has alignment requirement of 4), the entire structure will have the alignment requirement of 4 and its size will always be divisible by 4. 4 is the minimum size it can possibly have. Since you used only 18 bits for the bit-fields (3 bytes at least), the compiler managed to pack everything into 4 bytes. But it can't make it smaller than 4.
(Note, BTW, that just by counting the bits required gives us the total of 26. How on Earth you expected this to fit into 3 bytes, even ignoring any alignment considerations, is not clear to me.)
In your second structure you used 40 bits for the bit-fields (which involves 5 bytes already). Now the compiler is unable to pack everything into 4 bytes, so it uses 8 bytes. Again, the struct size is required to be divisible by 4, meaning that if 4 is not enough, then next smallest size is 8.
If you want to override that alignment behavior, you have to use your compiler-specific features to force the 1-byte alignment to all data types (#pragma pack
etc.). That way you might be able to reduce the size of your second struct. But what you observe now is perfectly expected under the default alignment settings.