468,161 Members | 2,092 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,161 developers. It's quick & easy.

Overflow Underflow


union SignedChoice{
long with_sign;
unsigned long without_sign;
};
int main()
{
SignedChoice data;

data.with_sign = -1;
//Right now, does the C++ Standard guarantee that
//data.without_sign == MAX_ULONGINT?

//Similarly:

data.without_sign = MAX_ULONGINT;

//Is data.with_sign now definitely == -1?

}
Is there any other interesting facts yous can give me?

-JKop
Jul 22 '05 #1
38 7813

"JKop" <NU**@NULL.NULL> wrote in message
news:PF*****************@news.indigo.ie...

union SignedChoice{
long with_sign;
unsigned long without_sign;
};
int main()
{
SignedChoice data;

data.with_sign = -1;
//Right now, does the C++ Standard guarantee that
//data.without_sign == MAX_ULONGINT?

//Similarly:

data.without_sign = MAX_ULONGINT;

//Is data.with_sign now definitely == -1?

}


I'm pretty sure that it doesn't. From what I understand, the standard does
not dictate the specific representation of a signed integer type (i.e,
whehter it's two's-complement, one's-complement, etc.). What is wel-defined
is the overflow/underflow behavior of an unsigned integer value, not its
direct equivelance to a signed integer value. So, adding x to a value to
casue an overflow can always be reversed by then subtracting x from that
result. Likewise, you can undo an underfolw by adding back the value
subtracted. But that doesn't neccessarily mean that s signed value of -1 is
the same bit representation as an unsigned value of max_whatever.

-Howard

Jul 22 '05 #2

Geez, how many typos can I make in one post??? I'll have to get my fingers
checked. :-)

-Howard
Jul 22 '05 #3
On Mon, 28 Jun 2004 16:27:27 GMT, JKop <NU**@NULL.NULL> wrote:

union SignedChoice{
long with_sign;
unsigned long without_sign;
};
int main()
{
SignedChoice data;

data.with_sign = -1;
//Right now, does the C++ Standard guarantee that
//data.without_sign == MAX_ULONGINT?
No, you can't write to one member of a union and read from another, at
least not like that (you can with structs with identical initial
sequences), so the point is moot.

If you are asking whether the bit pattern of -1 is guaranteed to be
all 1s, then the answer is no. 1's complement CPUs will give (for a
16-bit int):
1111111111111110
Sign magnitude CPUs will give:
1000000000000001

However, most CPUs these days do use 2s complement for signed numbers.
Is there any other interesting facts yous can give me?


Depending on your interests:
http://www.lingolex.com/ants.htm

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #4
Imagine a class that is absolutely massive in memory, maybe even a MB. You
want to swap two of these classes, and so obviously you don't want a
temporary. What do yous think of the following? I ain't got a compiler at
the moment so it's untested, and may be syntactically incorrect in places.
template<class Class> void Swap(Class& x, Class& y)
{
if ( (&x == &y) ) return;

unsigned char* const &pArrayX = reintepret_cast<unsigned char* const
&>(&x);
unsigned char* const &pArrayY = reinterpret_cast<unsigned char*
const &>(&y);

for ( unsigned char i = 0 ; i < sizeof(Class); ++i)
{
pArrayX[i] += pArrayY[i];

pArrayY[i] = pArrayX[i] - pArrayY[i];

pArrayX[i] -= pArrayY[i];
}
};
The only reason I define those references is for enhanced readability.

-JKop

Jul 22 '05 #5

"JKop" <NU**@NULL.NULL> wrote in message
news:Jk*****************@news.indigo.ie...
Imagine a class that is absolutely massive in memory, maybe even a MB. You
want to swap two of these classes, and so obviously you don't want a
temporary. What do yous think of the following? I ain't got a compiler at
the moment so it's untested, and may be syntactically incorrect in places.
template<class Class> void Swap(Class& x, Class& y)
{
if ( (&x == &y) ) return;

unsigned char* const &pArrayX = reintepret_cast<unsigned char* const &>(&x);
unsigned char* const &pArrayY = reinterpret_cast<unsigned char*
const &>(&y);

for ( unsigned char i = 0 ; i < sizeof(Class); ++i)
{
pArrayX[i] += pArrayY[i];

pArrayY[i] = pArrayX[i] - pArrayY[i];

pArrayX[i] -= pArrayY[i];
}
};
The only reason I define those references is for enhanced readability.

-JKop


Without looking at the code close enough to check the details, I see what
you're trying to do, and it won't always work. You can't always treat a
class as an array of unsigned char. If it contains non-POD types, I think
you get undefined behavior when writing to the array.

-Howard


Jul 22 '05 #6
JKop wrote:
Imagine a class that is absolutely massive in memory, maybe even a MB. You
want to swap two of these classes, and so obviously you don't want a
temporary. What do yous think of the following? I ain't got a compiler at
the moment so it's untested, and may be syntactically incorrect in places.


Generally, when classes, objects, instances or data is massive
in memory, you want to avoid swapping the beasts. Most programmers
use pointers to massive data and just swap the pointers.

If you don't want to use a temporary variable, then try swapping
individual members of the classes. One would say that less
memory is used swapping a class' member than the whole class.
This could even trickle down for aggregate and sub-classes.

Again, ask yourself why you are swapping the monstrosities
rather than pointers to them.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #7
Thomas Matthews posted:
JKop wrote:
Imagine a class that is absolutely massive in memory, maybe even a MB.
You want to swap two of these classes, and so obviously you don't want
a temporary. What do yous think of the following? I ain't got a
compiler at the moment so it's untested, and may be syntactically
incorrect in places.


Generally, when classes, objects, instances or data is massive
in memory, you want to avoid swapping the beasts. Most programmers
use pointers to massive data and just swap the pointers.

If you don't want to use a temporary variable, then try swapping
individual members of the classes. One would say that less
memory is used swapping a class' member than the whole class.
This could even trickle down for aggregate and sub-classes.

Again, ask yourself why you are swapping the monstrosities
rather than pointers to them.


Very good point, but I'm just doing this for fun. If I had to formulate a
bullshit reason for wanting to swap the values of variables I'd say
something like so:

A certain piece of hardware, Hardware A, is accessing a certain piece of
memory.

A certain piece of hardware, Hardware B, is accessing another certain piece
of memory.

You cannot change the address of the memory they're accessing so you've to
physically swap them around in memory.
-JKop
Jul 22 '05 #8
JKop wrote:
union SignedChoice{
long with_sign;
unsigned long without_sign;
};
int main()
{
SignedChoice data;

data.with_sign = -1;
//Right now, does the C++ Standard guarantee that
//data.without_sign == MAX_ULONGINT?
No since long and unsigned long are different types and they can be of
different size. Also their representation implementation may be
different, for example for one type it may be from left to right and for
the other from right to left (my mind has stuck and I do not recall the
exact terminology right now).

//Similarly:

data.without_sign = MAX_ULONGINT;

//Is data.with_sign now definitely == -1?

The same with what I told above.

}
Is there any other interesting facts yous can give me?

Have a slow thorough read of a good, up to date ISO C++ book like "The
C++ Programming Language" 3rd Edition or Special Edition by Bjarne
Stroustrup, the creator of C++.

However the last one is not for newcomers, and if you have not read any
other C++ introduction book *from cover to cover*, may be you had better
check "Accelerated C++" by Andrew Koenig, Barbara Moo.


Regards,

Ioannis Vranos
Jul 22 '05 #9
JKop wrote:
Imagine a class that is absolutely massive in memory, maybe even a MB.

Types do not occupy space, objects do. For example:

class A
{
int array[512];
};

The above definition does not occupy any space. However

A a;
does.

Objects occupying massive amounts of memory usually mean that there is
very bad design.

If you have container objects for example, the object itself is a
representation and when you swap you do not copy everything, but
exchange the internal structures (e.g. pointer variables pointing to
sequences on the free store).

In any case, stick with std::swap and provide specialisations of it for
your classes, in case you *can* perform some hand-written optimisations.
Otherwise the default one will be used (usually implemented to use a
temporary object).


Regards,

Ioannis Vranos
Jul 22 '05 #10
Howard wrote:
Without looking at the code close enough to check the details, I see what
you're trying to do, and it won't always work. You can't always treat a
class as an array of unsigned char. If it contains non-POD types, I think
you get undefined behavior when writing to the array.

Yes it is considered as a well-defined behaviour only for POD types. For
non-POD types it is guaranteed to be safe only reading the objects as
unsigned chars. If you write a copy of them, the copies are not
guaranteed to work.


Regards,

Ioannis Vranos
Jul 22 '05 #11
On Mon, 28 Jun 2004 23:07:11 +0300, Ioannis Vranos
<iv*@guesswh.at.grad.com> wrote:
JKop wrote:
union SignedChoice{
long with_sign;
unsigned long without_sign;
};
int main()
{
SignedChoice data;

data.with_sign = -1;
//Right now, does the C++ Standard guarantee that
//data.without_sign == MAX_ULONGINT?
No since long and unsigned long are different types and they can be of
different size.


They must have the same size and alignment requirements (aka object
representation).

Also their representation implementation may bedifferent, for example for one type it may be from left to right and for
the other from right to left (my mind has stuck and I do not recall the
exact terminology right now).


Nope, positive values of long must have the same bit pattern (aka
value representation) as the matching positive values of unsigned
long.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #12
tom_usenet posted:
Nope, positive values of long must have the same bit pattern (aka
value representation) as the matching positive values of unsigned
long.


which can be show by:

#include <iostream>

void Poo(unsigned long* p_cow)
{
cout << *p_cow;
}
int main()
{
long pig = 5400;

std::cout << pig << std::endl;

Poo(&pig); //Cast required? I ain't got a compiler

std::cout << std::endl;

std::system("PAUSE");

}
-JKop
Jul 22 '05 #13
JKop wrote in news:mK*****************@news.indigo.ie in comp.lang.c++:
Nope, positive values of long must have the same bit pattern (aka
value representation) as the matching positive values of unsigned
long.


which can be show by:


Reading the standard and *only* reading the standard.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #14
tom_usenet wrote:
No since long and unsigned long are different types and they can be of
different size.

They must have the same size and alignment requirements (aka object
representation).

Can you give me a reference in the standard where this is required?
Nope, positive values of long must have the same bit pattern (aka
value representation) as the matching positive values of unsigned
long.

Can you give me a reference in the standard where this is required?


Regards,

Ioannis Vranos
Jul 22 '05 #15
Ioannis Vranos wrote in news:cb***********@ulysses.noc.ntua.gr in
comp.lang.c++:
tom_usenet wrote:
No since long and unsigned long are different types and they can be of
different size.

They must have the same size and alignment requirements (aka object
representation).

Can you give me a reference in the standard where this is required?


3.9.1/3


Nope, positive values of long must have the same bit pattern (aka
value representation) as the matching positive values of unsigned
long.

Can you give me a reference in the standard where this is required?


3.9.1/3

Just FYI: I searched for "value representation" in my PDF copy of
the standard, the second click got me too 3.9.1/3. A search for
"object representation" would have got me there in three clicks.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #16
Rob Williscroft wrote:

3.9.1/3

Then JKOP is right!
#include <iostream>
union whatever
{
unsigned u;
signed i;
};
int main()
{
using namespace std;

whatever nice;

nice.i=-1;

cout<<nice.u<<" "<<static_cast<unsigned>(-1)<<endl;
}
Based on the standard nice.u above will always be equal to
numeric_limits<unsigned>::max()!


Regards,

Ioannis Vranos
Jul 22 '05 #17
Ioannis Vranos posted:
Rob Williscroft wrote:

3.9.1/3

Then JKOP is right!
#include <iostream>
union whatever
{
unsigned u;
signed i;
};
int main()
{
using namespace std;

whatever nice;

nice.i=-1;

cout<<nice.u<<" "<<static_cast<unsigned>(-1)<<endl;
}
Based on the standard nice.u above will always be equal to
numeric_limits<unsigned>::max()!

I love this country.
-JKop
Jul 22 '05 #18
JKop wrote:
I love this country.


Actually we are probably in different countries. :-)


Regards,

Ioannis Vranos
Jul 22 '05 #19
Ioannis Vranos posted:
JKop wrote:
I love this country.


Actually we are probably in different countries. :-)

Hence the irony ;-)... maybe I'm too ambitious.

-JKop
Jul 22 '05 #20
Ioannis Vranos wrote in news:cb***********@ulysses.noc.ntua.gr in
comp.lang.c++:
Rob Williscroft wrote:

3.9.1/3

Then JKOP is right!
#include <iostream>
union whatever
{
unsigned u;
signed i;
};
int main()
{
using namespace std;

whatever nice;

nice.i=-1;

cout<<nice.u<<" "<<static_cast<unsigned>(-1)<<endl;
}
Based on the standard nice.u above will always be equal to
numeric_limits<unsigned>::max()!


No on a 1's complement machine (say 16 bit for example:) -1 will
be represented in binary as 10000000 00000001 high bit (sign bit)
and byte first. unsigned( -1 ) is 11111111 11111111 which is
std::numeric_limits< unsigned >::max().

You must read the union member that was last assigned.

3.9.1/3 says that INT_MAX 01111111 1111111 has the same value
representation in signed and unsigned.

Doing:

nice.i = INT_MAX;
cout << nice.u;

is still UB, but in practice its only UB because the standard
says so. In theory (for example) a compiler could diagnose the
UB and refuse to compile, its UB, its free to *anything* it wants
and still be a conforming compiler.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #21
Ioannis Vranos wrote:
Based on the standard nice.u above will always be equal to
numeric_limits<unsigned>::max()!

Actually the standard states:

"For each of the signed integer types, there exists a corresponding (but
different) unsigned integer type: “unsigned char”, “unsigned short int”,
“unsigned int”, and “unsigned long int,” each of which occupies the same
amount of storage and has the same alignment requirements (3.9) as the
corresponding signed integer type 40) ; that is, each signed integer
type has the same object representation as its corresponding unsigned
integer type. The range of nonnegative values of a signed integer type
is a subrange of the corresponding unsigned integer type, and the value
representation of each corresponding signed/unsigned type shall be the same.

....

40) See 7.1.5.2 regarding the correspondence between types and the
sequences of type-specifiers that designate them."

So the above leaves it possible the signed(-1) and unsigned(-1) to have
a different value representation. signed(-2) and unsigned(-2) to have a
different representation and so on.
So as far as I can get it, the union thing is not guaranteed to work.
Any comments?


Regards,

Ioannis Vranos
Jul 22 '05 #22
Rob Williscroft wrote:
#include <iostream>
union whatever
{
unsigned u;
signed i;
};
int main()
{
using namespace std;

whatever nice;

nice.i=-1;

cout<<nice.u<<" "<<static_cast<unsigned>(-1)<<endl;
}
No on a 1's complement machine (say 16 bit for example:) -1 will
be represented in binary as 10000000 00000001 high bit (sign bit)
and byte first. unsigned( -1 ) is 11111111 11111111 which is
std::numeric_limits< unsigned >::max().

You must read the union member that was last assigned.

3.9.1/3 says that INT_MAX 01111111 1111111 has the same value
representation in signed and unsigned.

Yes.


Doing:

nice.i = INT_MAX;
cout << nice.u;

is still UB, but in practice its only UB because the standard
says so.

What do you mean? For non-negative values which are in range of both
types, they must have the same value representation.


Regards,

Ioannis Vranos
Jul 22 '05 #23
Ioannis Vranos wrote in news:cb***********@ulysses.noc.ntua.gr in
comp.lang.c++:
is still UB, but in practice its only UB because the standard
says so.

What do you mean? For non-negative values which are in range of both
types, they must have the same value representation.


Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard
says so. In theory (for example) a compiler could diagnose the
UB and refuse to compile, its UB, its free to *anything* it wants
and still be a conforming compiler.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #24
Rob Williscroft wrote:
Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard
says so.

Yes I meant, "where does the standard say so"?


Regards,

Ioannis Vranos
Jul 22 '05 #25
Ioannis Vranos <iv*@guesswh.at.grad.com> wrote:

Then JKOP is right!
Hardly
#include <iostream>

union whatever
{
unsigned u;
signed i;
};

int main()
{
using namespace std;
whatever nice;
nice.i=-1;
cout<<nice.u<<" "<<static_cast<unsigned>(-1)<<endl;
}
It's undefined behaviour to read any member of a union other than
the one that was most recently assigned (with the exception of the
case where the member read, and the most recently assigned member,
are 'struct's with a common initial sequence, and you read one of
the members of that common initial sequence).
Based on the standard nice.u above will always be equal to
numeric_limits<unsigned>::max()!


C and C++ work on values, not representations. -1 when static_cast
to an unsigned type will always be the maximum value of that type,
regardless of representation.

On the other hand, the representation of (int)-1 and (unsigned)-1
need not be the same (AFAICS), so even if the union example was
not UB, it still would not 'work'.

I suspect that reinterpret_cast<> will do what you are trying to do
with the union example (I don't have a 1's complement machine to
test it on though..)
Jul 22 '05 #26
Old Wolf posted:

It's undefined behaviour to read any member of a union other than
the one that was most recently assigned (with the exception of the
case where the member read, and the most recently assigned member,
are 'struct's with a common initial sequence, and you read one of
the members of that common initial sequence).


I know it's Undefined Behaviour to read from a double or a float without
prior initialization, ie.
double a;
float b;

a += 5.6;

b -= 6.2;
But... is it Undefined Behaviour to read from an uninitialized int? If
*not*, then contrary to you last post, there's nothing wrong with the
following:

union Chase
{
char black[sizeof(long)];
unsigned long blue;
};

int main()
{
Chase pursuit;

pursuit.black[0] = 5;
pursuit.black[1] = 2;
pursuit.black[2] = 6;
pursuit.black[3] = 88;

pursuit.blue += 4;
}
I last set it via black, but still there's nothing wrong with accessing it
via blue.
-JKop
Jul 22 '05 #27
JKop wrote:
But... is it Undefined Behaviour to read from an uninitialized int?

Actually it is.
Here are some definitions from the Standard:
1.3.12 undefined behavior
behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard imposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition
of behavior. [Note: permissible undefined behavior ranges from ignoring
the situation completely with unpredictable results, to behaving during
translation or program execution in a documented manner characteristic
of the environment (with or without the issuance of a diagnostic
message), to terminating a translation or execution (with the issuance
of a diagnostic message). Many erroneous program constructs do not
engender undefined behavior; they are required to be diagnosed. ]
1.3.13 unspecified behavior
behavior, for a well-formed program construct and correct data, that
depends on the implementation. The implementation is not required to
document which behavior occurs. [Note: usually, the range of possible
behaviors is delineated by this International Standard. ]"

As i have said in another message of mine, the union thing is not
guaranteed to work for values other than positive ones in the range
[0,maximum_positive_one_supported_by_the_smaller_ra nge_type].


Regards,

Ioannis Vranos
Jul 22 '05 #28
Ioannis Vranos wrote:
JKop wrote:
But... is it Undefined Behaviour to read from an uninitialized int?


Actually it is.
Here are some definitions from the Standard:
1.3.12 undefined behavior
behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard imposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition
of behavior. [Note: permissible undefined behavior ranges from ignoring
the situation completely with unpredictable results, to behaving during
translation or program execution in a documented manner characteristic
of the environment (with or without the issuance of a diagnostic
message), to terminating a translation or execution (with the issuance
of a diagnostic message). Many erroneous program constructs do not
engender undefined behavior; they are required to be diagnosed. ]
1.3.13 unspecified behavior
behavior, for a well-formed program construct and correct data, that
depends on the implementation. The implementation is not required to
document which behavior occurs. [Note: usually, the range of possible
behaviors is delineated by this International Standard. ]"

As i have said in another message of mine, the union thing is not
guaranteed to work for values other than positive ones in the range
[0,maximum_positive_one_supported_by_the_smaller_ra nge_type].

And another interesting behaviour is:

1.3.5 implementation-defined behavior
behavior, for a well-formed program construct and correct data, that
depends on the implementation and that each implementation shall document.


Regards,

Ioannis Vranos
Jul 22 '05 #29
Ioannis Vranos wrote in news:cb***********@ulysses.noc.ntua.gr in
comp.lang.c++:
Rob Williscroft wrote:
Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard
says so.

Yes I meant, "where does the standard say so"?


Section 9 Classes, 9.5 Unions, paragraph 1.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #30
Rob Williscroft wrote:
Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard
says so.

Yes I meant, "where does the standard say so"?

Section 9 Classes, 9.5 Unions, paragraph 1.

I read that and I did not find something that would cause undefined
behaviour, in the contrary it says:

"The size of a union is sufficient to contain the largest of its data
members. Each data member is allocated as if it were the sole member
of a struct."
which makes the behaviour well-defined for signed and unsigned integer
types in a union with a value in
[0, maximum_positive_value_supported_by_the_smaller_ra nge_type]


Regards,

Ioannis Vranos
Jul 22 '05 #31
Ioannis Vranos wrote:
Rob Williscroft wrote:
Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard says so.

Yes I meant, "where does the standard say so"?
Section 9 Classes, 9.5 Unions, paragraph 1.


I read that and I did not find something that would cause undefined
behaviour, in the contrary it says:

"The size of a union is sufficient to contain the largest of its data
members. Each data member is allocated as if it were the sole member
of a struct."
which makes the behaviour well-defined for signed and unsigned integer
types


of the same size,
in a union with a value in
[0, maximum_positive_value_supported_by_the_smaller_ra nge_type]



Regards,

Ioannis Vranos
Jul 22 '05 #32
Ioannis Vranos wrote:
I read that and I did not find something that would cause undefined
behaviour, in the contrary it says:

"The size of a union is sufficient to contain the largest of its data
members. Each data member is allocated as if it were the sole member
of a struct."
which makes the behaviour well-defined for signed and unsigned integer
types

of the same size,

of similar types (e.g. signed int with unsigned int)
in a union with a value in
[0, maximum_positive_value_supported_by_the_smaller_ra nge_type]



Regards,

Ioannis Vranos
Jul 22 '05 #33
Ioannis Vranos wrote in news:cb***********@ulysses.noc.ntua.gr in
comp.lang.c++:
Rob Williscroft wrote:
Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard
says so.
Yes I meant, "where does the standard say so"?
Section 9 Classes, 9.5 Unions, paragraph 1.

I read that and I did not find something that would cause undefined
behaviour, in the contrary it says:


The section (9.5) defines *all* the behaviour, that which it doesen't
define is *undefined*.
"The size of a union is sufficient to contain the largest of its data
members. Each data member is allocated as if it were the sole member
of a struct."

Irrelevant, you may only inspect the member that was most reciently
assigned too, *nothing* else is *defined* by the standard.

which makes the behaviour well-defined for signed and unsigned integer
types in a union with a value in
[0, maximum_positive_value_supported_by_the_smaller_ra nge_type]


Again:

.... In theory (for example) a compiler could diagnose the
UB and refuse to compile, its UB, its free to *anything* it wants
and still be a conforming compiler.

Also an implementation could have "type" bits in the object
representation of its signed and unsigned types, simply
reading the wrong union member could cause the CPU to fault.

If it *isn't* defined its undefined, whats so difficult
to understand about this.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #34
Rob Williscroft wrote:
which makes the behaviour well-defined for signed and unsigned integer
types in a union with a value in
[0, maximum_positive_value_supported_by_the_smaller_ra nge_type]

Again:

.... In theory (for example) a compiler could diagnose the
UB and refuse to compile, its UB, its free to *anything* it wants
and still be a conforming compiler.

Also an implementation could have "type" bits in the object
representation of its signed and unsigned types, simply
reading the wrong union member could cause the CPU to fault.

If it *isn't* defined its undefined, whats so difficult
to understand about this.

The only thing that makes you right and this undefined is the wording of
the standard:

"The size of a union is sufficient to contain the largest of its data
members."

The "sufficient" makes it undefined. If it were "equal to the largest of
its data members", it would not be undefined in any way.
So you are right, it is undefined, because in theory it can be larger
than the largest member and place them in a slightly different location.


Regards,

Ioannis Vranos
Jul 22 '05 #35
On Wed, 30 Jun 2004 02:16:07 +0300, Ioannis Vranos
<iv*@guesswh.at.grad.com> wrote:
Rob Williscroft wrote:
Yes, what I mean I said just after the bit you quoted, here it is
again:

is still UB, but in practice its only UB because the standard
says so.
Yes I meant, "where does the standard say so"?

Section 9 Classes, 9.5 Unions, paragraph 1.

I read that and I did not find something that would cause undefined
behaviour, in the contrary it says:

"The size of a union is sufficient to contain the largest of its data
members. Each data member is allocated as if it were the sole member
of a struct."
which makes the behaviour well-defined for signed and unsigned integer
types in a union with a value in
[0, maximum_positive_value_supported_by_the_smaller_ra nge_type]


Did you not read the very first sentence of 9.5/1? Seems pretty
clear...

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #36
tom_usenet wrote:
Did you not read the very first sentence of 9.5/1? Seems pretty
clear...

Yes you are right, I just noticed it.


Regards,

Ioannis Vranos
Jul 22 '05 #37
JKop <NU**@NULL.NULL> wrote:
Old Wolf posted:
It's undefined behaviour to read any member of a union other than
the one that was most recently assigned (with the exception of the
case where the member read, and the most recently assigned member,
are 'struct's with a common initial sequence, and you read one of
the members of that common initial sequence).
But... is it Undefined Behaviour to read from an uninitialized int?


Yes. It's UB to access an indeterminate value, and uninitialized
variables all have indeterminate value.
If *not*, then contrary to you last post, there's nothing wrong with the
following:

union Chase
{
char black[sizeof(long)];
unsigned long blue;
};
pursuit.black[0] = 5;
pursuit.black[1] = 2;
pursuit.black[2] = 6;
pursuit.black[3] = 88;
pursuit.blue += 4;


This is nothing to do with reading from uninitialized variables.
Perhaps you missed what I said above:
It's undefined behaviour to read any member of a union other than
the one that was most recently assigned


Your example is a union, and you assign 'black' and then read 'blue'.
Your code is still UB even if you assign something to blue before
you assign to black.

If you want an exact reference in the standard, do a text search
for 'union' on your pirate copy
Jul 22 '05 #38
Old Wolf posted:
If you want an exact reference in the standard, do a text search
for 'union' on your pirate copy

I don't have a copy, hence the requests.
-JKop
Jul 22 '05 #39

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Paul Emmons | last post: by
5 posts views Thread by Ian Pilcher | last post: by
4 posts views Thread by Raymond | last post: by
11 posts views Thread by pereges | last post: by
1 post views Thread by gcdp | last post: by
reply views Thread by gcreed | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.