Using void* and class*

Pages: 12

This code is an example of a programmer bypassing the type system. The compiler can only syntax check that:
1. A can be initialised with 5.
2. A and B have member's called i, but it doesn't check that they're at the same offset within the struct/class.

It's more complicated than offsets.
Even if i is at the same offset this code may not work(and does not work in my example as it output 5 with -O2 with i at the same offset).


An more detailled explanation on why:
The types A and B are not alias types as defined by the strict-aliasing rule so the compiler is allowed to assume that *b and a can't be at the same memory location.
So if they are not at the same memory location this means variable a is never modified.
And if a is never modified the compiler can replace a.i of line 4 by 5 "safely". In fact a is really modified at line 3 but line 4 doesn't use it, that why it will print 5.

This means this code:
1
2
3
4
5
6
A a = {5};
B* b = reinterpret_cast<B*>(&a);
b->i = 500;
cout << a.i << endl;
a.i += 5;
cout << a.i;

could perfectly print 5 then 505 (and does it with -O2).
although I've heard some horror stories about gcc's strict aliasing policy


"horror stories"? This is no horror stories, the section 3.10, item 15 of the c++ standard(rvalues and lvalues) exist for this purpose: it allows the compiler to do peacefully its optimizations like the one mentioned above.
See:

If a program attempts to access the stored value of an object through an lvalue of other than one of the
following types the behavior is undefined52
— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type similar (as defined in 4.4) to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type
of the object,
— an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic
data members (including, recursively, an element or non-static data member of a subaggregate
or contained union),
— a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
— a char or unsigned char type.
"horror stories"? This is no horror stories,


There may not be for you, but how the undefined behavior is handled doesn't seem to be a QoI issue to you. To those it is, horror stories exist. I would wager if Linus Torvalds didn't have a horror story to relate, he wouldn't have written:

http://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg01647.html

Apparently the reason I didn't get a warning is because gcc doesn't automatically enable the warning when it automatically enables strict aliasing. Even with -Wall and -pedantic, the strict-aliasing warning has to be specifically enabled.

I came across http://dbp-consulting.com/tutorials/StrictAliasing.html the other day, and it seemed very concise in a plain-language sort of way so, sharing!

Which version of mingw are you using? I use the 4.4 and I set only -Wall for warning, I didn't have to add more warnings...

I would wager if Linus Torvalds didn't have a horror story to relate


Do you know the positions of Linus Torvalds about C++? Being myself a C++ programmer, I can't really agree with the point of view of someone who says C++ is an horrible language.

But I perfectly understand that people like you or Linus Torvalds prefer C over C++, it's a choice.

So I agree this may be an horror story for a C programmer as it's doesn't really fit with the C philosophy
I can do everithing I want and the compiler shut up
but for a C++ point of view this part of the standard and the optimisatizations it allows is perfectly natural.
Last edited on
That's not actually a C philosophy, that's the perverse "portable assembler" philosophy. C is write once compile anywhere. 9-bit bytes? 1's complement negatives? Decimal floating-point numbers? It's all the same for a C program.
Which version of mingw are you using? I use the 4.4 and I set only -Wall for warning, I didn't have to add more warnings...


4.6.2

According to the documentation those warnings are supposed to be enabled with -O2 and -Wall, but not the experience I'm having.



Do you know the positions of Linus Torvalds about C++? Being myself a C++ programmer, I can't really agree with the point of view of someone who says C++ is an horrible language.


So, people who use C++ but don't necessarily see eye-to-eye with you on certain issues cannot express concerns or criticisms about the QoI of a compiler without them being summarily dismissed by you? Good to know.

So I agree this may be an horror story for a C programmer as it's doesn't really fit with the C philosophy
I can do everithing I want and the compiler shut up
but for a C++ point of view this part of the standard and the optimisatizations it allows is perfectly natural.


That is certainly not a C philosophy. But I understand why people like you and other language bigots (Hey look, I can lump you in with other people too!) wouldn't bother to find out if the assertion they were making was true. C has had strict aliasing rules since.. what? At least c89?

Most of the horror stories I've heard involve gcc breaking pre-existing code quietly, without warning.

Hey sorry I didn't want to start a war ( it's true my last post can be interpreted that way so I apologize), my point was not to lump you with other people, really.

For C having strict aliasing rules from c89 i knew it, what i wanted to said is that some people(which i respect, don't misinterpret my worlds) who do low level programming(and which I associate with pure C programmer) can be bothered by this rule and I understand it. But I find this rule natural for C++.

I hope you understand better my point now and I will stop this debate as I don't like arguing with people.
Topic archived. No new replies allowed.
Pages: 12