Order of Variable

S

shaanxxx

i have following class

Class A
{
public :
int a;
int b;
int c;
}

Class B
{
public :
int a;
int b;
}

can i take pointer of type *B and point to class A Object and
successfully modify Data member a and b of A . What standard has to
say about it ?

B * ptr = reinterpret_cast<B*>( new A );


Are Data members laid in memory in order in which they are declared ?
 
I

Ian Collins

i have following class

Class A
{
public :
int a;
int b;
int c;
}

Class B
{
public :
int a;
int b;
}

can i take pointer of type *B and point to class A Object and
successfully modify Data member a and b of A .

Probably, but why would you want to?
What standard has to say about it ?

Not a lot, because its silly and unnecessary.
B * ptr = reinterpret_cast<B*>( new A );

Are Data members laid in memory in order in which they are declared ?

For POD structs, yes.
 
A

Alf P. Steinbach /Usenet

* shaanxxx, on 10.09.2010 05:36:
i have following class

Class A
{
public :
int a;
int b;
int c;
}

Class B
{
public :
int a;
int b;
}

can i take pointer of type *B and point to class A Object and
successfully modify Data member a and b of A . What standard has to
say about it ?

In C++98 you're formally in UB-land when you try that on non-POD types such as
above.

For POD types the standard supports it via the discussion of layout-compatible
types in §9.2, and in particular support of reinterpret_cast from first member
in struct to struct and vice versa in §9.2/17.

This support is there because it was/is a common technique in C. In C++ you
simply use inheritance instead. No reinterpret_cast required then. :)

B * ptr = reinterpret_cast<B*>( new A );

Here you're on shaky ground because you need to deallocate via an A* pointer.

Also this problem is solved by inheritance, combined with a virtual destructor.

Are Data members laid in memory in order in which they are declared ?

As long as there's no intervening access specifier, yes. Later members are then
at higher addresses than earlier members. However, there can be padding between
them (although not before the first member of POD).


Cheers & hth.,

- Alf
 
S

shaanxxx

Probably, but why would you want to?


Not a lot, because its silly and unnecessary.



For POD structs, yes.

You can think of class B as old implementation and A is new
implementation. If you dont specify data member c , implementation
will set C to some default value .
 
S

shaanxxx

Probably, but why would you want to?


Not a lot, because its silly and unnecessary.



For POD structs, yes.

What happens if I add non-virtual member function to
1) Class A
2) Class A and Class B
3) Class B
 
T

tni

* shaanxxx, on 10.09.2010 05:36:

In C++98 you're formally in UB-land when you try that on non-POD types
such as above.

For POD types the standard supports it via the discussion of
layout-compatible types in §9.2, and in particular support of
reinterpret_cast from first member in struct to struct and vice versa in
§9.2/17.

Things aren't quite that rosy. You still violate the aliasing rules and
there enough compilers that will happily generate wrong code.

The only safe thing to do is memcpy or using a union (if your C++
compiler supports C99 semantics for the union access, the C++ standard
itself doesn't really allow it).
 
S

Stuart Redmann

The standard says that your program will produce UB.
What happens if I add non-virtual member function to
1) Class A
2) Class A and Class B
3) Class B- Zitierten Text ausblenden -

Why don't you just try it and see? You could also buy this book
"Inside the C++ Object Model" from Stan Lippman, which Victor Bazarov
recommended in his quite recent posting
(e-mail address removed).

You should have noted by now that the standard doesn't give you any
guarantee that your code is going to work. Any further questions
whether some code will work should be asked in a newsgroup that is
dedicated to the particular compiler you are using.

Regards,
Stuart
 
C

cpp4ever

i have following class

Class A
{
public :
int a;
int b;
int c;
}

Class B
{
public :
int a;
int b;
}

can i take pointer of type *B and point to class A Object and
successfully modify Data member a and b of A . What standard has to
say about it ?

B * ptr = reinterpret_cast<B*>( new A );


Are Data members laid in memory in order in which they are declared ?

I would strongly discourage doing this, even if it appears to work,
there is no guarantee it will work on another platform, or for future
updates. The type of thing you are trying to do should be implemented
using public inheritance as shown below.


class B
{
public:
int a;
int b;
};

class A : public B
{
public:
int c;
};


B *ptr = new A;


HTH

cpp4ever
 
G

Goran Pusic

i have following class

Class A
{
public :
int a;
int b;
int c;

}

Class B
{
public :
int a;
int b;

}

can i take pointer of type *B and point to class A Object and
successfully modify Data member a and b of A . What standard has to
say about it ?

;-)

I don't think you should care about the standard. I think you should
care about solving your actual problem, which I guess is interfacing
two parts of the code, where you control one. Well, the one you do
control, you can either derive from A from B or vice-versa, or use
composition and avoid any hacks.

IOW, what are you trying to do in the grander scheme of things?

Goran.
 
A

Alf P. Steinbach /Usenet

* tni, on 10.09.2010 08:31:
Things aren't quite that rosy. You still violate the aliasing rules and there
enough compilers that will happily generate wrong code.

Nah to both. :)


The only safe thing to do is memcpy or using a union (if your C++ compiler
supports C99 semantics for the union access, the C++ standard itself doesn't
really allow it).

Ouch.

It's an old C technique. No compiler will foul it up. Don't add needless complexity.


Cheers & hth.,

- ALf
 
J

Johannes Schaub (litb)

tni said:
Things aren't quite that rosy. You still violate the aliasing rules and
there enough compilers that will happily generate wrong code.

The only safe thing to do is memcpy or using a union (if your C++
compiler supports C99 semantics for the union access, the C++ standard
itself doesn't really allow it).

C++ and C99 seem to have exactly the same semantics for these things. With
both one violates aliasing. If I am wrong, would you please be so kind to
point out the difference? Thanks!
 
J

Johannes Schaub (litb)

Johannes said:
C++ and C99 seem to have exactly the same semantics for these things. With
both one violates aliasing. If I am wrong, would you please be so kind to
point out the difference? Thanks!

Does 6.5/6 "The effective type of an object for an access to its stored
value is the declared type of the object, if any." apply to union members?
I.e is the effective type of the read of an union member its declared type?
In such a case, I can see how C99's semantics differ from C++.

C++ seems to determine the type of the accessed object based on "reuse" of
its memory according to 3.8: A write to a "non-active" union member changes
its type by starting its lifetime with another type (the one of that member)
because it "reuses" the storage of the currently active member, effectively
ending lifetime of that member's object.
 
A

Alf P. Steinbach /Usenet

* Johannes Schaub (litb), on 10.09.2010 18:19:
C++ and C99 seem to have exactly the same semantics for these things. With
both one violates aliasing. If I am wrong, would you please be so kind to
point out the difference? Thanks!

Actual concrete aliasing is constrained by the rules for layout-compatibility
and pointer conversion from/to first member.

Thus there's only the potential for violation when the aliasing rules are
considered in isolation.

But they cannot meaningfully be considered in isolation.


Cheers & hth.,

- Alf
 
T

tni

* tni, on 10.09.2010 08:31:

Nah to both. :)

I've seen something like that miscompiled by g++ (IIRC somewhere around
version 4.0).
Ouch.

It's an old C technique. No compiler will foul it up. Don't add needless
complexity.

What's your point?

This:
float f;
int i = *(int*) &f;

is an old C technique as well with lots of code using it.

What makes you think it's not a violation of the aliasing rules? Given
your reference to the first member, you did notice that the OP wanted to
access the second one as well, right?

(I can see the argument that access to the first member might be safe.
But the language in the standard isn't really explicit that you are not
violating the aliasing rules and that's always dangerous.)
 
A

Alf P. Steinbach /Usenet

* tni, on 11.09.2010 00:14:
I've seen something like that miscompiled by g++ (IIRC somewhere around version
4.0).


What's your point?

This:
float f;
int i = *(int*) &f;

is an old C technique as well with lots of code using it.

What makes you think it's not a violation of the aliasing rules? Given your
reference to the first member, you did notice that the OP wanted to access the
second one as well, right?

The rule about sharing a common initial sequence, in a union.

In C++0x N2092 it's §9.2/17, the paragraph number may be slightly off wrt. C++98.

(I can see the argument that access to the first member might be safe. But the
language in the standard isn't really explicit that you are not violating the
aliasing rules and that's always dangerous.)

It is quite explicit.

You just have to realize that aliasing and layout is constrained by other rules.


Cheers & hth.,

- Alf
 
T

tni

The rule about sharing a common initial sequence, in a union.

In C++0x N2092 it's §9.2/17, the paragraph number may be slightly off
wrt. C++98.

That only says that things work in a union. What does it have to do with
aliasing for the non-union case?
 
A

Alf P. Steinbach /Usenet

* tni, on 11.09.2010 08:41:
That only says that things work in a union. What does it have to do with
aliasing for the non-union case?

Assuming that by "aliasing" you mean "alignment", C++0x §9.2/17 doesn't have to
do with alignment requirements of the types. It has to do with the second of
your two questions, quoted above, which was about layout. Alignment requirements
of the types is much simpler.

Consider:

struct PseudoBase { char c; };
struct PseudoDerived{ char c; double d; };

PseudoDerived derived;
PseudoBase* p = reinterpret_cast< PseudoBase >( &derived );

If this cast "up" to PseudoBase* is fine, then casting back "down" to
PseudoDerived* is no problem, it's covered by reinterpret_cast rules.

So alignment can only be a problem for this pseudo upcast.

Namely if PseudoBase, with fewer members, has a stricter alignment, say,
PseudoBase alignment is 16 while PseudoDerived alignment is just 4.

And that's not going to happen. :)

OK, it's not AFAIK specified by the standard, but it requires a perverse
implementation. Such perverse implementations do not exist any more than an
implementation with sizeof(bool) > 1E9 (which is also a formal possibility). In
practice you can rely on the implementation to not foul it up, as I mentioned
up-thread -- perhaps it's more clear now what that would entail.


Cheers & hth.,

- Alf
 
T

tni

Assuming that by "aliasing" you mean "alignment", C++0x §9.2/17 doesn't
have to do with alignment requirements of the types. It has to do with
the second of your two questions, quoted above, which was about layout.
Alignment requirements of the types is much simpler.

No, I'm not talking about alignment at all (which is certainly
guaranteed). I'm talking about the strict aliasing rules.

The two structs are different types and the compiler is IMHO allowed to
assume that they don't really occupy the same storage or overlap (and
thus may reorder/optimize away access which may result in wrong code).
 
A

Alf P. Steinbach /Usenet

* tni, on 11.09.2010 13:53:
No, I'm not talking about alignment at all (which is certainly guaranteed). I'm
talking about the strict aliasing rules.

The two structs are different types and the compiler is IMHO allowed to assume
that they don't really occupy the same storage or overlap (and thus may
reorder/optimize away access which may result in wrong code).

Not entirely sure what you're talking about. I vaguely remember g++ having some
"strict aliasing" bug. Hopefully that's not it?

Could you give a concrete, minimal but complete example where you think that
access could be "reorder/optimize away"?


Cheers,

- Alf (baffled)
 
T

tni

Not entirely sure what you're talking about. I vaguely remember g++
having some "strict aliasing" bug. Hopefully that's not it?

Could you give a concrete, minimal but complete example where you think
that access could be "reorder/optimize away"?

I can't give you a simple example, but what I have seen is similar to
the behavior in this case (in my complex case, the structs started with
the same sequence):

#include <iostream>
#include <stdint.h>

struct A {
uint32_t x;
uint32_t y;
};

struct B {
float x;
uint32_t y;
};

int main() {
A a = A();
B& b = *reinterpret_cast<B*>(&a);
b.x = 42;
std::cout << a.x << " " << b.x << std::endl;
return 0;
}

Output (g++ -O2):
0 42
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top