Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

size differences

40 views
Skip to first unread message

Christopher Pisz

unread,
Dec 18, 2017, 7:15:48 PM12/18/17
to
The following assert is failing. Is this a known thing with standard c++ or with the compiler I happen to be using?


class S1
{
public:
int m1;
char m2;
char m3;
};

class S2
{
public:
int m1;
char m2;
public:
char m3;
};

int main()
{
assert(sizeof(S1) == sizeof(S2));
}

Öö Tiib

unread,
Dec 18, 2017, 7:47:52 PM12/18/17
to
It must be the compiler that you are using since I can't reproduce it
with any I can reach.

C++ does not have concept of "layout-compatible types" like C has so
I think the behavior is legal and does not violate standards.

Chris M. Thomasson

unread,
Dec 18, 2017, 8:03:39 PM12/18/17
to
What compiler are you using? Keep in mind that these are not POD's.

Here is a little program:
______________________
#include <cassert>
#include <iostream>

class S1
{
public:
int m1;
char m2;
char m3;
};

class S2
{
public:
int m1;
char m2;
public:
char m3;
};

int main()
{
std::cout << "sizeof(S1) == " << sizeof(S1) << "\n";
std::cout << "sizeof(S2) == " << sizeof(S2) << "\n";
assert(sizeof(S1) == sizeof(S2));
return 0;
}
______________________

So far, I cannot get it to trip the assert.

Ian Collins

unread,
Dec 18, 2017, 8:16:53 PM12/18/17
to
It looks like a bug - they should have the same layout if all the
members have the same access control. Which compiler was this?

Try adding

#include <type_traits>

static_assert( std::is_standard_layout<S1>::value,
"S1 not standard layout" );
static_assert( std::is_standard_layout<S2>::value,
"S2 not standard layout" );
static_assert( sizeof(S1) == sizeof(S2),
"S1 and S2 differ");

and see what you get.

--
Ian.

Alf P. Steinbach

unread,
Dec 19, 2017, 1:59:30 AM12/19/17
to
On 12/19/2017 2:16 AM, Ian Collins wrote:
> On 12/19/2017 01:15 PM, Christopher Pisz wrote:
>> The following assert is failing. Is this a known thing with standard
>> c++ or with the compiler I happen to be using?
>>
>>
>> class S1
>> {
>> public:
>>         int m1;
>>         char m2;
>>         char m3;
>> };
>>
>> class S2
>> {
>> public:
>>         int m1;
>>         char m2;
>> public:
>>         char m3;
>> };
>>
>> int main()
>> {
>>      assert(sizeof(S1) == sizeof(S2));
>> }
>
>
> It looks like a bug - they should have the same layout if all the
> members have the same access control.

With C++11 rules yes. With C++03 it was about an "intervening access
specifier", IIRC.


Cheers!,

- Alf

James Kuyper

unread,
Dec 19, 2017, 2:13:50 PM12/19/17
to
On 12/18/2017 07:47 PM, Öö Tiib wrote:
...
> C++ does not have concept of "layout-compatible types" like C has so
> I think the behavior is legal and does not violate standards.

The latest version of the C++ standard that I have on my system is
n3797.pdf, 2013-10-13. I uses the term "layout-compatible" twice in
3.9p11, one each in 3.9.2p2 and 7.2p9, twice in 9.2p16 and 9.2p17, and
one last time in 9.2p18.
The term never appears anywhere in the C standard.

James Kuyper

unread,
Dec 19, 2017, 2:31:01 PM12/19/17
to
I'm using n3797.pdf for my citations.

"Two standard-layout struct (Clause 9) types are layout-compatible if
they have the same number of non-static data members and corresponding
non-static data members (in declaration order) have layout-compatible
types (3.9)." (9.2p16)

Note that "A standard-layout class ... has the same access control
(Clause 11) for all non-static data members". (9p7), a condition met by
both S1 and S2.

I expected the standard to assert somewhere that layout-compatible types
have the same size and the same value of offsetof() for each non-static
data member. But if there's any such guarantee, I've been unable to
locate it.

About the only constraint I could find on the layout of non-static data
members is that "If two pointers point to different non-static data
members of the same object, or to subobjects of such members,
recursively, the pointer to the later declared member compares greater
provided the two members have the same access control (Clause 11) and
provided their class is not a union." (5.9p3).

Ian Collins

unread,
Dec 19, 2017, 2:44:10 PM12/19/17
to
std::is_standard_layout<T> is your friend.

--
ian

bartc

unread,
Dec 19, 2017, 2:46:32 PM12/19/17
to
What are the two sizes?

--
bartc

Öö Tiib

unread,
Dec 19, 2017, 2:55:04 PM12/19/17
to
Yes. I remembered it wrongly. There is layout-compatibility in C++ for
union members with common initial sequence. I meant the sufficiently
similar types of C that were concept of compatible types. I believe
the S1 and S2 of OP were such types until C99.

James Kuyper

unread,
Dec 19, 2017, 3:18:13 PM12/19/17
to
All citations in this message are from the C standard, not the C++ one.

The only difference between S1 and S2 involves a feature ("public:") not
supported by C99. If you drop that feature, they are compatible types,
but only if declared in separate translation units (6.2.7p1), and
nothing changed in that regard in C99.

6.2.7p1 is a peculiar feature of the C standard that deserves some
explanation. You might think that two struct types declared identically
in different translation units would be considered to declare the same
type, but "The presence of a struct-declaration-list in a
struct-or-union-specifier declares a new type, within a translation
unit." The fact that the type's scope is restricted to that translation
unit means that the rule that "Two types have compatible type if their
types are the same." (6.2.7p1) doesn't allow you to say that struct
types defined identically in different translation units are compatible
with each other. Therefore, 6.2.7p1 was added to say that they are.

However, the C standard deliberately restricts that rule to types
declared in separate translation units. If you define two struct types
identically in one translation unit, it's assumed that you deliberately
intended them to be distinct types, and that you would therefore want to
get the diagnostic messages you will get if you accidentally mix them up
in contexts where relevant types are required to be compatible.

The fact that they are incompatible allows certain optimizations, based
mainly upon the anti-aliasing rules, but because they would be
compatible with identical declarations in a different translation unit,
an implementation is not free to lay them out differently unless it can
be certain that they won't be used for communication between translation
units.

James Kuyper

unread,
Dec 19, 2017, 3:20:05 PM12/19/17
to
On 12/19/2017 02:43 PM, Ian Collins wrote:
> On 12/20/2017 08:30 AM, James Kuyper wrote:
...
>> I'm using n3797.pdf for my citations.
>>
>> "Two standard-layout struct (Clause 9) types are layout-compatible if
>> they have the same number of non-static data members and corresponding
>> non-static data members (in declaration order) have layout-compatible
>> types (3.9)." (9.2p16)
>>
>> Note that "A standard-layout class ... has the same access control
>> (Clause 11) for all non-static data members". (9p7), a condition met by
>> both S1 and S2.
>>
>> I expected the standard to assert somewhere that layout-compatible types
>> have the same size and the same value of offsetof() for each non-static
>> data member. But if there's any such guarantee, I've been unable to
>> locate it.
>>
>> About the only constraint I could find on the layout of non-static data
>> members is that "If two pointers point to different non-static data
>> members of the same object, or to subobjects of such members,
>> recursively, the pointer to the later declared member compares greater
>> provided the two members have the same access control (Clause 11) and
>> provided their class is not a union." (5.9p3).
>
>
> std::is_standard_layout<T> is your friend.

It merely allows you to identify that a class is a standard layout
class. It doesn't impose any additional requirements on the layout of
the class, so it doesn't resolve the issue I raised.
0 new messages