[xpost] a new C/C++ type that when overflow i see it

¬

¬a\\/b

this would be an example for using nasm and a c++ compiler all
together (for doing a 32 bits type that overflow if something goes
wrong)

using assembly and c++ has some disadvantage (because compiler has to
use all the same operation for doing something (that i should
reproduce in assembly))
then i not understand many function that compiler use in the code
(that i not add)

but all this has the vantage of reduce written text code
and if you have to write something that use the structure of type
"ou32" you have to write more than me

then i would say that type "ou32" is better of your beloved size_t
that all you use in malloc and all the routines that has to deal with
arrays

not because is more fast but because it has the controll on overflow
that size_t can not to have

can you please point out to some error do you see below?
what do you think on it?

thank you
-----------------------------------
; nasm file of name "nasmfile.asm"
; nasmw -fobj nasmfile.asm

section _DATA public align=4 class=DATA use32

align 16 , db 0
ffffffff dt 4294967295.0
fake dt 0.0
offffffff dq 4294967295.0

global @$badd$q4ou32t1 , @$bsub$q4ou32t1 , @$bmul$q4ou32t1
global @$bdiv$q4ou32t1 , @ou32@$bctr$qv , @ou32@$bctr$qi
global @ou32@$bctr$qg , @ou32@$bctr$qui , @ou32@$bctr$qpc
global @ou32@$bctr$qs , @ou32@$bctr$qd , @ou32@$bctr$qus
global @ou32@$bctr$qr4ou32 , @ou32@$brplu$q4ou32
global @ou32@$brmin$q4ou32 , @ou32@$brmul$q4ou32
global @ou32@$brdiv$q4ou32 , @$blss$q4ou32t1
global @$bleq$q4ou32t1 , @$bgtr$q4ou32t1
global @$bgeq$q4ou32t1 , @ou32@$od$qv , @ou32@$oi$qv
global @ou32@$oui$qv , @ou32@$og$qv , @ou32@$binc$qv
global @ou32@$bdec$qv , @ou32@$binc$qi , @ou32@$bdec$qi
global @$beql$q4ou32t1 , @$bneq$q4ou32t1



section _TEXT public align=1 class=CODE use32


; ou32 operator+(ou32 a, ou32 b)
; 0ra, 4P_AddressResult, 8P_a, 12P_b
@$badd$q4ou32t1:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [ esp + 12 ]
cmp ecx, -1
je .0
cmp edx, -1
je .0
add ecx, edx
jc .0
mov dword[eax], ecx
ret
..0:
mov dword[eax], -1
ret


; ou32 operator-(ou32 a, ou32 b)
@$bsub$q4ou32t1:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [ esp + 12 ]
cmp ecx, -1
je .0
cmp edx, -1
je .0
sub ecx, edx
jl .0
mov dword[eax], ecx
ret
..0:
mov dword[eax], -1
ret


; ou32 operator*(ou32 a, ou32 b)
@$bmul$q4ou32t1:
mov eax, [ esp + 8 ]
mov ecx, [ esp + 12 ]
cmp eax, -1
je .0
cmp ecx, -1
je .0
mul ecx
cmp edx, 0
jne .0
mov ecx, eax
mov eax, [ esp + 4 ]
mov dword[eax], ecx
ret
..0:
mov eax, [ esp + 4 ]
mov dword[eax], -1
ret

; a, c, r si possono usare
; ou32 operator/(ou32 a, ou32 b)
; 0ra, 4P_AddResult, 8P_a, 12P_b
@$bdiv$q4ou32t1:
mov eax, [ esp + 8 ]
mov ecx, [ esp + 12 ]
cmp eax, -1
je .0
cmp ecx, -1
je .0
xor edx, edx
div ecx
mov ecx, eax
mov eax, [ esp + 4 ]
mov dword[eax], ecx
ret
..0:
mov eax, [ esp + 4 ]
mov dword[eax], -1
ret


; int operator==(ou32 a, ou32 b)
@$beql$q4ou32t1:
mov eax, [ esp + 4 ]
sub eax, [esp+8]
jz .0
mov eax, 0
ret
..0:
mov eax, 1
ret
ret

; int operator!=(ou32 a, ou32 b)
@$bneq$q4ou32t1:
mov eax, [ esp + 4 ]
sub eax, [esp+8]
jz .0
mov eax, 1
ret
..0:
mov eax, 0
ret
ret

; int operator<(ou32 a, ou32 b)
; 1-2=-1<0 <=> 1<2
@$blss$q4ou32t1:
mov eax, [ esp + 4 ]
sub eax, [esp+8]
jb .0
mov eax, 0
ret
..0:
mov eax, 1
ret


; int operator<=(ou32 a, ou32 b)
@$bleq$q4ou32t1:
mov eax, [ esp + 4 ]
sub eax, [esp+8]
jbe .0
mov eax, 0
ret
..0:
mov eax, 1
ret


; int operator>(ou32 a, ou32 b)
@$bgtr$q4ou32t1:
mov eax, [ esp + 4 ]
sub eax, [esp+8]
ja .0
mov eax, 0
ret
..0:
mov eax, 1
ret



; int operator>=(ou32 a, ou32 b)
@$bgeq$q4ou32t1:
mov eax, [ esp + 4 ]
sub eax, [esp+8]
jae .0
mov eax, 0
ret
..0:
mov eax, 1
ret


; ou32::eek:u32(long double a)
@ou32@$bctr$qg:
sub esp, 8
mov ecx, [ esp + 12 ] ; a>0xFFFFFFF
FLD tword[esp+16] ; st=a
FCOM qword[offffffff]
FSTSW ax
sahf
jbe .0
FSTP qword[esp]
mov dword[ecx], 0xFFFFFFFF
jmp short .1
..0:
FISTP qword[esp]
mov edx, [esp]
mov [ecx], edx
..1:
mov eax, ecx
add esp, 8
ret

; ou32::eek:u32(double a)
; 0_1, 4_2, 8ra, 12P_this, 16P_a
@ou32@$bctr$qd:
sub esp, 8
mov ecx, [ esp + 12 ] ; a>0xFFFFFFF
FLD qword[esp+16] ; st=a
FCOM qword[offffffff]
FSTSW ax
sahf
jbe .0
FSTP qword[esp]
mov dword[ecx], 0xFFFFFFFF
jmp short .1
..0:
FISTP qword[esp]
mov edx, [esp]
mov [ecx], edx
..1:
mov eax, ecx
add esp, 8
ret

; ou32::eek:u32(char* a)
; ou32::eek:u32(unsigned a)
; 0ra, 4P_This, 8P_a
@ou32@$bctr$qpc:
@ou32@$bctr$qui:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov [eax], ecx
ret

; ou32::eek:u32(int a)
@ou32@$bctr$qi:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
cmp ecx, 0
jge .0
mov dword[eax], -1
ret
..0:
mov [eax], ecx
ret

; i can use eax, ecx, edx for the abi call
; ou32::eek:u32(short a)
; 0ra, 4P_This, 8P_a
@ou32@$bctr$qs:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
cmp cx, 0
jge .0
mov dword[eax], -1
ret
..0:
and ecx, 0xFFFF
mov [eax], ecx
ret

; ou32::eek:u32(unsigned short a)
@ou32@$bctr$qus:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
and ecx, 0xFFFF
mov [eax], ecx
ret

; ou32::eek:u32()
@ou32@$bctr$qv:
mov eax, [ esp + 4 ]
mov dword[eax], 0
ret


; ou32::eek:u32(ou32& a)
; NB: not in use
; 0ra, 4P_This, 8P_a
@ou32@$bctr$qr4ou32:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
cmp eax, ecx
je .0
mov edx, [ecx]
mov [eax], edx
..0:
ret

; ou32 ou32::eek:perator+=(ou32 a)
; 0ra, 4P_this, 8P_a
@ou32@$brplu$q4ou32:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [eax]
cmp ecx, -1
je .0
cmp edx, -1
je .0
add ecx, edx
jc .0
mov dword[eax], ecx
ret
..0:
mov dword[eax], -1
ret


; ou32 ou32::eek:perator-=(ou32 a)
@ou32@$brmin$q4ou32:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [eax]
cmp ecx, -1
je .0
cmp edx, -1
je .0
sub ecx, edx
jl .0
mov dword[eax], ecx
ret
..0:
mov dword[eax], -1
ret



; ou32 ou32::eek:perator*=(ou32 a)
@ou32@$brmul$q4ou32:
mov edx, [ esp + 4 ]
mov eax, [ esp + 8 ]
mov ecx, [edx]
cmp eax, -1
je .0
cmp ecx, -1
je .0
mul ecx
cmp edx, 0
jne .0
mov ecx, eax
mov eax, [ esp + 4 ]
mov dword[eax], ecx
ret
..0:
mov eax, [ esp + 4 ]
mov dword[eax], -1
ret


; ou32 ou32::eek:perator/=(ou32 a)
@ou32@$brdiv$q4ou32:
mov edx, [ esp + 4 ]
mov eax, [ esp + 8 ]
mov ecx, [edx]
cmp eax, -1
je .0
cmp ecx, -1
je .0
xor edx, edx
div ecx
mov ecx, eax
mov eax, [ esp + 4 ]
mov dword[eax], ecx
ret
..0:
mov eax, [ esp + 4 ]
mov dword[eax], -1
ret


; ou32::eek:perator double()
; ou32::eek:perator long double()
; 0F[0], 4F[1], 8ra, 12this
@ou32@$od$qv:
@ou32@$og$qv:
sub esp, 8
mov eax, [ esp + 12 ]
mov ecx, [eax]
mov dword[esp], ecx
mov dword[esp+4], 0
fild qword[esp]
add esp, 8
ret

; ou32::eek:perator int()
; ou32::eek:perator unsigned()
; 0ra, 4this
@ou32@$oi$qv:
@ou32@$oui$qv:
mov ecx, [ esp + 4 ]
mov eax, [ecx]
ret



; ou32 ou32::eek:perator++()
; 0ra, 4P_AddressResult, 8P_this
@ou32@$binc$qv:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [ecx]
cmp edx, -1
je .0
inc edx
mov [eax], edx
mov [ecx], edx
ret
..0:
mov dword[eax], -1
ret


; ou32 ou32::eek:perator--()
@ou32@$bdec$qv:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [ecx]
cmp edx, -1
je .0
dec edx
mov [eax], edx
mov [ecx], edx
ret
..0:
mov dword[eax], -1
ret


; ou32 ou32::eek:perator++(int)
@ou32@$binc$qi:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [ecx]
cmp edx, -1
je .0
mov [eax], edx
inc edx
mov [ecx], edx
ret
..0:
mov dword[eax], -1
ret


; ou32 ou32::eek:perator--(int)
@ou32@$bdec$qi:
mov eax, [ esp + 4 ]
mov ecx, [ esp + 8 ]
mov edx, [ecx]
cmp edx, -1
je .0
mov [eax], edx
dec edx
mov [ecx], edx
ret
..0:
mov dword[eax], -1
ret


; end nasm file

/* Begin Borland C++ file of name borlfile.cpp */
/* bcc32 borlfile.cpp nasmfile.obj */
/* "bcc32" is the Borland compiler */

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>

class ou32
{public:
ou32(); /* convertitori */
ou32(unsigned a);
ou32(int a);
ou32(double a);
ou32(long double a);
ou32(char* a);
ou32(short a);
ou32(unsigned short a);
// ou32(ou32& a);
// ################
friend ou32 operator+(ou32 a, ou32 b);
friend ou32 operator-(ou32 a, ou32 b);
friend ou32 operator*(ou32 a, ou32 b);
friend ou32 operator/(ou32 a, ou32 b);

friend int operator<(ou32 a, ou32 b);
friend int operator<=(ou32 a, ou32 b);
friend int operator>(ou32 a, ou32 b);
friend int operator>=(ou32 a, ou32 b);

friend int operator==(ou32 a, ou32 b);
friend int operator!=(ou32 a, ou32 b);


friend istream& operator>>(istream& istr, ou32& a)
{return istr >> a.v;}
friend ostream& operator<<(ostream& ostr, ou32 a)
{return ostr << a.v;}

// ################
ou32 operator+=(ou32 a);
ou32 operator-=(ou32 a);
ou32 operator*=(ou32 a);
ou32 operator/=(ou32 a);
ou32 operator++();
ou32 operator++(int);
ou32 operator--();
ou32 operator--(int);

// ################
operator double();
operator int();
operator unsigned();
operator long double();
// ################
unsigned v;
};

char* mallocI(size_t v){return (char*) v;}

char* mallocII(ou32 a)
{if(a==(ou32) -1) return 0;
else return mallocI(a.v);
}

int main(void)
{long double oo;
double m;
unsigned u0, u1, r0;
ou32 a=9.0, b=21.0, c, r;
c=a+b;
printf("Il valore di c==%u\n", c);
oo=c; m=c;
printf("Il val.longdouble==%Lf"
" val.double= %f\n", oo, m);
c=-1;
printf("Valore iniziale == %x\n", c);
++c;
printf("Il valore di c==%x\n", c.v);
--c;
printf("Il valore di c==%x\n", c.v);

// you can try to overflow data here
l1:;
printf("Per uscire a==0, b==0, c==0\n");
printf("Inserisci il valore a> ");
if( scanf("%u", &a)!=1 ) return 0;
printf("Preso %u \n", a);
printf("Inserisci il valore b> ");
if( scanf("%u", &b)!=1 ) return 0;
printf("%c ", a<b? '+': (a==b? '=': '-'));
printf("Preso %u \n", b);
printf("Inserisci il valore c> ");
if( scanf("%u", &c)!=1 ) return 0;
printf("Preso %u \n", c);

r=a*b+c; r0=a.v*b.v+c.v;
printf("Risultato a*b+c=%u\n", r);
u0=(unsigned) mallocI(r0);
u1=(unsigned) mallocII(r);
printf("You can see how mallocI return a vector of %u bytes\n", u0);
printf("While mallocII return a vector of %u bytes \n", u1);
printf("The words \"0 bytes\" means that malloc return null\n");
if(r0!=0) goto l1;
return 0;
}

/*
note how beautifull are these numbers...
Inserisci il valore a> 429497
Preso 429497
Inserisci il valore b> 10000
Preso 10000
Inserisci il valore c> 90
Preso 90
Risultato a*b+c=4294967295
You can see how mallocI return a vector of 2794 bytes
While mallocII return a vector of 0 bytes
The words "0 bytes" means that malloc return null
Per uscire a==0, b==0, c==0
*/
 
M

Malcolm McLean

¬a\/b said:
this would be an example for using nasm and a c++ compiler all
together (for doing a 32 bits type that overflow if something goes
wrong)
Nice idea, integers that kick if abused.
Implement in C++ and see if the C++ operator overloading feature is all it
is cracked up to be.

In C the idea is unusable, because you need an explicit call for every
operation, and the code just isn't human-readable any more. However you
could propose another 10 types or so to add to the 14 integer types we
already have.
 
J

jacob navia

¬a\/b said:
this would be an example for using nasm and a c++ compiler all
together (for doing a 32 bits type that overflow if something goes
wrong)

using assembly and c++ has some disadvantage (because compiler has to
use all the same operation for doing something (that i should
reproduce in assembly))
then i not understand many function that compiler use in the code
(that i not add)

but all this has the vantage of reduce written text code
and if you have to write something that use the structure of type
"ou32" you have to write more than me

then i would say that type "ou32" is better of your beloved size_t
that all you use in malloc and all the routines that has to deal with
arrays

not because is more fast but because it has the controll on overflow
that size_t can not to have

can you please point out to some error do you see below?
what do you think on it?

thank you
-----------------------------------
[assembly code snipped for brevity]

This approach could (maybe) work, but the problem is that (at least in
C, do not know about C++) overflow is well defined for unsigned integers
or in general unsigned quantities. The result of that operation should
"wrap around".

What is NOT defined, is overflow with signed integers. This distinction
is not apparent in the code you posted.

In my opinion, this should be implemented in the compiler. In the
lcc-win32 compiler a compile time option lets you test for overflow each
of the four operations with signed numbers. This has many advantages,
above all it is simpler to use than having a new integer class. Even if
lcc-win32 implements operator overloading as an extension, I think the
code would have too much of a slowdown if for each addition you would
call a function, even if that function is inlined...

Concerning the assembler code you posted, I do not understand why you
test for carry and NOT for overflow. In my implementation at least, I
test for OVERFLOW after each operation and not just for the carry...

jacob
 
K

Keith Thompson

jacob navia said:
In my opinion, this should be implemented in the compiler. In the
lcc-win32 compiler a compile time option lets you test for overflow
each of the four operations with signed numbers. This has many
advantages,
above all it is simpler to use than having a new integer class. Even if
lcc-win32 implements operator overloading as an extension, I think the
code would have too much of a slowdown if for each addition you would
call a function, even if that function is inlined...

What's an "integer class"? Do you mean "integer type"? (I see this
is cross-posted to comp.lang.c and comp.lang.c++, almost always a bad
idea -- but the OP is a known troll.)

Since overflow checking is perfectly valid in standard C, I'll ask
something about lcc-win32's implementation of it. You said "the four
operations"; I assume that means "+", "-", "*", "/". Does it check
for overflow *only* on those for operations? What about unary "-"?
"++"? "--"? "<<"? Conversions?

I'd almost rather not have overflow checking at all than have it only
for a limited set of operations.
 
J

jacob navia

Keith said:
What's an "integer class"? Do you mean "integer type"? (I see this
is cross-posted to comp.lang.c and comp.lang.c++, almost always a bad
idea -- but the OP is a known troll.)

Since overflow checking is perfectly valid in standard C, I'll ask
something about lcc-win32's implementation of it. You said "the four
operations"; I assume that means "+", "-", "*", "/". Does it check
for overflow *only* on those for operations? What about unary "-"?
"++"? "--"? "<<"? Conversions?

I'd almost rather not have overflow checking at all than have it only
for a limited set of operations.

Well, ++ and -- are additions and subtractions as far as I remember...
:)

No, I do not check for overflow with <<. It makes no sense actually.

Unary minus can generate overflow only with -INT_MIN, I believe, so
it is a borderline case. Is it really worth the effort?

But you have a point here. At least in the case of unary minus it
is a valid point.

jacob
 
K

Keith Thompson

jacob navia said:
Keith Thompson wrote: [...]
Since overflow checking is perfectly valid in standard C, I'll ask
something about lcc-win32's implementation of it. You said "the four
operations"; I assume that means "+", "-", "*", "/". Does it check
for overflow *only* on those for operations? What about unary "-"?
"++"? "--"? "<<"? Conversions?
I'd almost rather not have overflow checking at all than have it only
for a limited set of operations.

Well, ++ and -- are additions and subtractions as far as I remember...
:)

Which doesn't answer the question. They're often implemented using
different machine instructions, and they may be handled separately
within the compiler. Users of lcc-win32 would probably be interested
in knowing whether it performs overflow checking on "++" and "--"
operators, and you haven't said whether it does or not.
No, I do not check for overflow with <<. It makes no sense actually.

So if someone writes 'x << 3' rather than the equivalent 'x * 8'
because he thinks it's more efficient (or because he's compiling
legacy code written to cater to old compilers where it really is
significantly more efficient), then he's going to lose overflow
checking?
Unary minus can generate overflow only with -INT_MIN, I believe, so
it is a borderline case. Is it really worth the effort?

<SARCASM>
No, not at all. Don't trouble yourself about it. I'm sure that would
*never* happen.
</SARCASM>

Unary minus can overflow. Make up your mind, are you doing overflow
checking, or aren't you?
But you have a point here. At least in the case of unary minus it
is a valid point.

If I were going to implement overflow checking, I'd carefully go
through every operation defined by the language, determine whether it
can ever overflow, and generate checks accordingly. I'd also look
carefully at floating-point, which you haven't mentioned.

Of course, since the behavior on signed integer overflow is undefined,
a compiler that checks for overflow only when the left operand is even
and the right operand is prime could be conforming. It's just a QoI
issue.
 
A

Army1987

Well, ++ and -- are additions and subtractions as far as I remember...
:)

No, I do not check for overflow with <<. It makes no sense actually.
More sense than with divisions, how on Earth could they overflow?
 
K

Keith Thompson

Army1987 said:
More sense than with divisions, how on Earth could they overflow?

INT_MIN / (-1)

FLT_MIN / 0.01

It's also unclear whether lcc-win32 checks for division by zero, or
for floating-point overflow.

It doesn't really matter from a C language point of view (or C++,
sorry for continuing the inappropriate crosspost, followups redirected
to comp.lang.c). I actually like the idea of (optional) overflow
checking in C; it's permitted by the standard for signed and
floating-point types, and it doesn't even require an extension. It
would be nice to have an example of a compiler that does this
properly, but it appears we'll have to look elsewhere.
 
¬

¬a\\/b

¬a\/b said:
this would be an example for using nasm and a c++ compiler all
together (for doing a 32 bits type that overflow if something goes
wrong)

using assembly and c++ has some disadvantage (because compiler has to
use all the same operation for doing something (that i should
reproduce in assembly))
then i not understand many function that compiler use in the code
(that i not add)

but all this has the vantage of reduce written text code
and if you have to write something that use the structure of type
"ou32" you have to write more than me

then i would say that type "ou32" is better of your beloved size_t
that all you use in malloc and all the routines that has to deal with
arrays

not because is more fast but because it has the controll on overflow
that size_t can not to have

can you please point out to some error do you see below?
what do you think on it?

thank you
-----------------------------------
[assembly code snipped for brevity]

This approach could (maybe) work, but the problem is that (at least in
C, do not know about C++) overflow is well defined for unsigned integers
or in general unsigned quantities. The result of that operation should
"wrap around".

there are operation where "wrap around" is a big error
(note how size_t is used always in the C standard library)
What is NOT defined, is overflow with signed integers. This distinction
is not apparent in the code you posted.

the same i write for unsigned type can be rewrite for signed
In my opinion, this should be implemented in the compiler. In the
lcc-win32 compiler a compile time option lets you test for overflow each
of the four operations with signed numbers. This has many advantages,
above all it is simpler to use than having a new integer class. Even if
lcc-win32 implements operator overloading as an extension, I think the
code would have too much of a slowdown if for each addition you would
call a function, even if that function is inlined...

yes
Concerning the assembler code you posted, I do not understand why you
test for carry and NOT for overflow. In my implementation at least, I
test for OVERFLOW after each operation and not just for the carry...

i use carry for unsigned types because i can do all with "jc" for
unsigned types (and never found the need of use "jo" for unsigned
until now)
 
J

jacob navia

Keith said:
INT_MIN / (-1)

FLT_MIN / 0.01

It's also unclear whether lcc-win32 checks for division by zero, or
for floating-point overflow.

No, since integer division by zero will trap, making finding
the error easy.

Floating point overflow is well defined by the language and
I did not interfere with that.

[snip polemic]
 
U

user923005

Keith said:
Army1987 said:
On Fri, 10 Aug 2007 00:58:22 +0200, jacob navia wrote: [...]
No, I do not check for overflow with <<. It makes no sense actually.
More sense than with divisions, how on Earth could they overflow?
INT_MIN / (-1)
FLT_MIN / 0.01
It's also unclear whether lcc-win32 checks for division by zero, or
for floating-point overflow.

No, since integer division by zero will trap, making finding
the error easy.

Unless it happens once every ten thousand invocations of the program,
making it incrediby difficult to find.
Floating point overflow is well defined by the language and
I did not interfere with that.
[snip]
 
J

jacob navia

user923005 said:
Keith said:
]
No, I do not check for overflow with <<. It makes no sense actually.
More sense than with divisions, how on Earth could they overflow?
INT_MIN / (-1)
FLT_MIN / 0.01
It's also unclear whether lcc-win32 checks for division by zero, or
for floating-point overflow.
No, since integer division by zero will trap, making finding
the error easy.

Unless it happens once every ten thousand invocations of the program,
making it incrediby difficult to find.

Well, and my compiler tests would succeed once
every ten thousand. It is the same!

I do not see any advantage of sofwtare checking
when the hardware does it anyway.
 
R

Richard Bos

Keith Thompson said:
What's an "integer class"? Do you mean "integer type"? (I see this
is cross-posted to comp.lang.c and comp.lang.c++, almost always a bad
idea -- but the OP is a known troll.)

He is. It is interesting to note who has taken his suggestion seriously.
It is depressing to see who is taking _their_ replies seriously.

Richard
 
J

jacob navia

Richard said:

At least he posts his work here, not like many others that limits
themselves to empty gestures.

There is a real need to catch overflow that has been completely
neglected by the language.


It is interesting to note who has taken his suggestion seriously.

Those that have worked with this problem, and proposed a working
solution, with a freely available implementation.
It is depressing to see who is taking _their_ replies seriously.

YOU for instance. You participate in this thread :)

But obviously you do not count!
 
K

Keith Thompson

Army1987 said:
Army1987 said:
On Fri, 10 Aug 2007 00:58:22 +0200, jacob navia wrote: [...]
No, I do not check for overflow with <<. It makes no sense actually.
More sense than with divisions, how on Earth could they overflow?

INT_MIN / (-1) Right.

FLT_MIN / 0.01
1. We're talking about integers.

We were talking about overflow; I decided to talk about floating-point
overflow as well as integer overflow.
2. It doesn't overflow, for two reasons. You were thinking about
DBL_MAX?

You're right, DBL_MAX is a better example.

Two reasons?
 
A

Alan Curry

You're right, DBL_MAX is a better example.

Two reasons?

FLT_MIN/0.01 is within the range of a float - you made it bigger instead of
smaller.

and

FLT_MIN/100.0 (what you really meant) is pretty likely to be within the range
of a double which is the precision actually used for the operation.

And maybe a couple more reasons: the loss of accuracy in FLT_MIN/(float)100
(what you really really meant) is an underflow, not an overflow; and it might
not lose accuracy at all in a floating point system with denormals. But that
would probably require decimal floating point so I bet it wasn't one of the
original two reasons.
 
K

Keith Thompson

FLT_MIN/0.01 is within the range of a float - you made it bigger instead of
smaller.

Argh, my mistake. I was thinking that FLT_MIN is a large negative
number, typically -FLT_MAX; in fact, it's a tiny positive number.
and

FLT_MIN/100.0 (what you really meant) is pretty likely to be within the range
of a double which is the precision actually used for the operation.

And maybe a couple more reasons: the loss of accuracy in FLT_MIN/(float)100
(what you really really meant) is an underflow, not an overflow; and it might
not lose accuracy at all in a floating point system with denormals. But that
would probably require decimal floating point so I bet it wasn't one of the
original two reasons.

Yeah, I should have used double, specifically DBL_MAX.
 
J

jacob navia

Floating point overflow
-----------------------

The standard defines clearly what happens with floating point overflow.
The set of floating point environment flags is handled by the fe.*
functions and described in the standard header fenv.h

The user can set/unset and query those flags after/§before each floating
point operation.

This is a major improvement over the outdated C89 situation. See the
section 7.6 of the standard.

It is a pity that the standard did NOT specify what happens with integer
overflow, even if indirectly acknowledges that the operation results
in undefined behavior.

This is why it is not correct to mix floating point and integer overflow.
One is well defined, the other is not.

jacob
 
K

Keith Thompson

jacob navia said:
Floating point overflow
-----------------------

The standard defines clearly what happens with floating point overflow.
The set of floating point environment flags is handled by the fe.*
functions and described in the standard header fenv.h

Isn't support for that optional? In other words, I think a conforming
implementation can do anything it likes on floating-point overflow, as
long as it doesn't claim IEC 60599 conformance.

But it's good that the standard provides a description of how FP
overflow is to be handled for implementations that choose to do so.

The standard explicitly states that conversion to a floating-point
type invokes undefined behavior if the value cannot be represented in
the target type. And C99 6.5p5 says:

If an _exceptional condition_ occurs during the evaluation of an
expression (that is, if the result is not mathematically defined
or not in the range of representable values for its type), the
behavior is undefined.

(This doesn't apply to unsigned types, since reduction modulo 2**N is
part of the operation, so formally speaking the overflow doesn't
happen in the first place.)

[...]
It is a pity that the standard did NOT specify what happens with integer
overflow, even if indirectly acknowledges that the operation results
in undefined behavior.

Did you mean "directly" rather than "indirectly"?
This is why it is not correct to mix floating point and integer overflow.
One is well defined, the other is not.

There is a significant difference, in that the standard provides an
*optional* framework for dealing with floating-point overflow; an
implementer who wants to do something similar for signed integer
overflow pretty much has to define the interfaces.

It's possible I'm misreading the standard; if so, please point out
where I'm mistaken.
 

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,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top