0

I am looking for a way to get the orginal size of a struct/class before the compiler aligned it ( more clearly let's say the sum of the member fields of the struct/class ) like this :

struct Foo{
   char c;
   // the compiler will appen 3 bytes here
   int i;
};

The sizeof(Foo) returns 8 but the orginal size is 5 .

suppose we want to write a template function or a macro named orig_sizeof()

template <class t>
size_t orig_sizeof(t)
{
   // calculate the sum of the fields of t
}

Of course sizeof is an internal macro , a keyword macro that has no source code .

A possible way to to it is by changing the structure aligment using __attribute__ or #pragma than getting the size using sizeof after that resturing the aligment to default ( maybe c++11's decltype can be useful ! ), any ideas about a useful implentation ?

Edit : im trying to write an optimized library that doesn't accept as argument an not optimized struct/class , by comparing sizeof(type) with orig_sizeof(type) , and asking the user to realign feilds for better performance if possible

Dhia Hassen
  • 508
  • 4
  • 20
  • 1
    No, its not possible. – πάντα ῥεῖ Oct 02 '16 at 17:23
  • 2
    1) Don't spam tags. C is not C++ is not C. 2) Why do you think the size of an object changes with alignment? 3) If `sizeof(Foo) == 8`, the size of `Foo` **is** `8`. – too honest for this site Oct 02 '16 at 17:23
  • 2
    There is no such thing as an "original size". You simply have a wrong image of the C++ type system. – Kerrek SB Oct 02 '16 at 17:24
  • ofc it does , the compiler appends extra bytes to the structure , you can try it yourself , compare `sizeof ( struct { char c;char c1;int x; }; )` with `sizeof ( struct {char c; int x;char c1; }; ) ` they are 8 and 12 respectivly – Dhia Hassen Oct 02 '16 at 17:26
  • @DhiaHassen The compiler optimizes the memory. What's the purpose of what you are asking? I'm struggling to understand. – peval27 Oct 02 '16 at 17:28
  • @peval27 He wants to know the sum of applying `sizeof(T)` to every data member. – user2296177 Oct 02 '16 at 17:29
  • @Kerrek SB i don't think i do , i was carefuly and intensely reading about that topic the few passed week for my project , maybe i used the wrong word , lets say orig_size = the size of the structure if the compiler didn't append any bytes for aligment – Dhia Hassen Oct 02 '16 at 17:29
  • @peval27 im trying to write an optimized library that doesn't accept as argument an not optimized struct/class , by comparing sizeof(type) with orig_sizeof(type) , and asking the user to realign feilds for better performance if possible – Dhia Hassen Oct 02 '16 at 17:31
  • sorry for spelling mistakes , i edited the comment , and thanks – Dhia Hassen Oct 02 '16 at 17:34
  • @DhiaHassen Fair enough. Could I suggest to change the title to: Is **it** possible to get the **original** size of the class/struct before compiler align it? – peval27 Oct 02 '16 at 17:38
  • @peval27 done , so there is no possible way !? what about something like sizeof( __declspec(packed)(struct name)) ! or something close , maybe my using metaprogramming – Dhia Hassen Oct 02 '16 at 17:44
  • @DhiaHassen The honest answer is I don't know. There are similar question on SO though: https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member – peval27 Oct 02 '16 at 17:53
  • yeah i have read that , now it is a good chance to learn advanced metaprogramming – Dhia Hassen Oct 02 '16 at 17:56

2 Answers2

0

No. C++ does not offer that functionality. In future, when one of the many reflection proposals will make their way into Standard, you might be able to get sizes of all members. However it is essentually pointless and it is impossible to do what you want. Here is why:

1) In your example struct {char; int; }; will always be 8 bytes long, no matter the order of members. there always will be 3 bytes of padding: either between char and int, at the end, 1 between int and char and 2 at the end... It is impossible to build "effectivelly packed" struct using standard C++.

2) Inheritance. Compiler can reuse padding in parent structs for child members. Subset of this is Empty Base Optimisation, which can make whole object size to be less than sum of its bases and members. Or not. EBO is not mandatory. Have fun trying to determine if EBO was just not triggered and struct is "effectivelly packed" or it was triggered and you have 2 stray bytes of padding somewhere.

3) Dynamic dispatch facilities. Usually it is another invisible pointer member (or several in case of multiple inheritance) in your class, which will add its own aligment requirements to the class. Then (1) applies. What is worse, you cannot change where those pointers will be placed.

Revolver_Ocelot
  • 8,609
  • 3
  • 30
  • 48
0

You could define the struct in a separate header with conditional compilation for packing:

struct 
#ifdef pack
__attribute__((packed))
PackedFoo
#else
Foo
#endif
{
  char c;
  int i;
};

Then use the preprocessor to include a packed and unpacked version of the struct:

#include "foo.hpp"
#define pack
#include "foo.hpp"

This would allow you to observe the two sizes as if it were the same type:

//custom sizeof for packed representation
#define sizeof_packed(type) sizeof(Packed##type)

int main(){

  std::cout << sizeof(Foo) << '\n';        //prints 8
  std::cout << sizeof_packed(Foo) << '\n'; //prints 5
}
Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271