The reason why the sizeof operator is returning 16 for your C1 struct is derived from:
1) 4 bytes for pointer to your struct C due to virtual inheritance
2) 4 bytes for C1::f(), for pointer to function on vtable
3) 4 bytes for C1::f1(), again for pointer to function on vtable
4) 4 bytes for C1::C1() constructor again vtable pointer
You don't get anything for C::f() as you have hidden this due to C1::f()
Why do you keep saying "... the correct 12 bytes" ? The sizeof operator is returining the correct size for the argv you give it. If you take the C1 constructor out then you are getting 12 i.e. see my initial response and ignore the last 4 bytes i.e. (4). Don't forget that it will align along a 4 byte boundary.
Who cares what value it's set to? Why is zero meaningless? Should we just get rid of 0 altogether? Who needs it?
I called the virtual functionof base/derived/most derived from base/derived/most derived (all combinations) with and without the #pragma, I get the same result except for the difference of 4 bytes
Are you familiar with what virtual inheritance is used for? If yes, then why do you think your example here is realistic? Even if it were realistic, one would presume this follows the same principle as undefined behavior. That is, sometimes the undefined behavior is (or seems to be) the expected behavior. That doesn't make it a good idea.
My best guess is that VS2012 does not need these 4 bytes , other compilers may need them and to create the same memory map, vs2012 adds these 4 bytes and sets them to zero
Since virtual base pointer is not available i.e. information on data slicing is not available, these 4 bytes may be used to keep this information hardcoded.
(need a different compiler to verify this).
In vs2012 ,(by debugging and watching the memory dump) virtual base pointer is initialized before any base constructor is called , hence data slicing inormation is available.