Overflow Underflow

J

JKop

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
 
H

Howard

JKop said:
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
 
H

Howard

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

-Howard
 
J

JKop

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 += pArrayY;

pArrayY = pArrayX - pArrayY;

pArrayX -= pArrayY;
}
};


The only reason I define those references is for enhanced readability.

-JKop
 
T

tom_usenet

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
 
H

Howard

JKop said:
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 += pArrayY;

pArrayY = pArrayX - pArrayY;

pArrayX -= pArrayY;
}
};


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
 
T

Thomas Matthews

JKop said:
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
 
J

JKop

Thomas Matthews posted:
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
 
I

Ioannis Vranos

JKop said:
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
 
I

Ioannis Vranos

JKop said:
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
 
I

Ioannis Vranos

Howard said:
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
 
T

tom_usenet

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 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).

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

Tom
 
J

JKop

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
 
I

Ioannis Vranos

tom_usenet said:
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
 
R

Rob Williscroft

Ioannis Vranos wrote in in
comp.lang.c++:
Can you give me a reference in the standard where this is required?
3.9.1/3



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.
 
I

Ioannis Vranos

Rob Williscroft wrote:



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
 
J

JKop

Ioannis Vranos posted:
Rob Williscroft wrote:




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
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top