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

Discussion in 'C Programming' started by ¬a\\/b, Aug 9, 2007.

  1. ¬a\\/b

    ¬a\\/b Guest

    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
    */
     
    ¬a\\/b, Aug 9, 2007
    #1
    1. Advertisements

  2. 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.
     
    Malcolm McLean, Aug 9, 2007
    #2
    1. Advertisements

  3. ¬a\\/b

    jacob navia Guest

    [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
     
    jacob navia, Aug 9, 2007
    #3
  4. 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.
     
    Keith Thompson, Aug 9, 2007
    #4
  5. ¬a\\/b

    jacob navia Guest

    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
     
    jacob navia, Aug 9, 2007
    #5
  6. 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.
    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?
    <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?
    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.
     
    Keith Thompson, Aug 10, 2007
    #6
  7. ¬a\\/b

    Army1987 Guest

    More sense than with divisions, how on Earth could they overflow?
     
    Army1987, Aug 10, 2007
    #7
  8. 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.
     
    Keith Thompson, Aug 10, 2007
    #8
  9. ¬a\\/b

    ¬a\\/b Guest

    there are operation where "wrap around" is a big error
    (note how size_t is used always in the C standard library)
    the same i write for unsigned type can be rewrite for signed
    yes
    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)
     
    ¬a\\/b, Aug 10, 2007
    #9
  10. ¬a\\/b

    jacob navia Guest

    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]
     
    jacob navia, Aug 10, 2007
    #10
  11. ¬a\\/b

    user923005 Guest

    Unless it happens once every ten thousand invocations of the program,
    making it incrediby difficult to find.
    [snip]
     
    user923005, Aug 10, 2007
    #11
  12. ¬a\\/b

    jacob navia Guest

    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.
     
    jacob navia, Aug 10, 2007
    #12
  13. ¬a\\/b

    Army1987 Guest

    1. We're talking about integers.
    2. It doesn't overflow, for two reasons. You were thinking about
    DBL_MAX?
     
    Army1987, Aug 10, 2007
    #13
  14. ¬a\\/b

    Richard Bos Guest

    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
     
    Richard Bos, Aug 10, 2007
    #14
  15. ¬a\\/b

    jacob navia Guest

    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.
    YOU for instance. You participate in this thread :)

    But obviously you do not count!
     
    jacob navia, Aug 10, 2007
    #15
  16. We were talking about overflow; I decided to talk about floating-point
    overflow as well as integer overflow.
    You're right, DBL_MAX is a better example.

    Two reasons?
     
    Keith Thompson, Aug 10, 2007
    #16
  17. ¬a\\/b

    Alan Curry Guest

    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.
     
    Alan Curry, Aug 10, 2007
    #17
  18. 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.
    Yeah, I should have used double, specifically DBL_MAX.
     
    Keith Thompson, Aug 10, 2007
    #18
  19. ¬a\\/b

    jacob navia Guest

    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
     
    jacob navia, Aug 10, 2007
    #19
  20. 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.)

    [...]
    Did you mean "directly" rather than "indirectly"?
    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.
     
    Keith Thompson, Aug 10, 2007
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.