1

The below example does not work as I expected (using ">" in the conditional) with GCC on an 8 bit machine, and neither on Linux 64 bit. If I make Timer_Secs and FutureTimeout_1Minute f.ex. 16 bits wide (int in those cases is 16 bits) it works as it should (using ">" in the conditional).

So, to get this to work for 8 bits with sign I seem to have to use "==" in the conditional.

{
    // Example with 8-bit only as tested with GCC 3.2 on AVR ATmega 128
    unsigned int  Cnt1 = 0; // 16 bits (kind of system clock)
    unsigned int  Cnt2 = 0; // 16 bits (observer, see what happens)
    signed   char Timer_Secs = 0; // 8 bits with sign
    signed   char FutureTimeout_1Minute = 60; // 8 bits with sign

    while (Cnt1 < 602) 
    { //                                         ## 
        if ((Timer_Secs - FutureTimeout_1Minute) == 0)
        {
            FutureTimeout_1Minute += 60; // Overflow/underflow allowed, 
                                         // so wraps and changes sign 
            Cnt2++; 
        } else {} // No code
        Timer_Secs++; 
        Cnt1++;
    } 
    //                 ## 
    // Cnt2 is 35 if >  0 above   #define AFTER_F(a,b)    ((a-b)>0)
    // Cnt2 is 35 if >= 0 above   #define AFTER_EQ_F(a,b) ((a-b)>=0)
    // Cnt2 is 10 if == 0 above   #define AFTER_ON_F(a,b) ((a-b)==0) **EXPECTED!**
}

The compare seems to involve some kind of sign conversion. I have not studied the assembly code for the different cases, since I thought this could be solved at code level.

  • Why is this so?
  • To me this looks plain wrong?
  • Still I assume it's compiled like this by design?
  • Is there some kind of type transfer or type decoration I could have done?

The context here is a blog note called "Know your timer's type" at: [blog]: http://www.teigfam.net/oyvind/home/technology/109-know-your-timers-type/

Disclaimer: this is a private blog with no money, ads, free things for me or etc. involved. Neither I nor anybody get anything from clicking on this url nor any of the urls in any of my blog notes.

It works as expected in Go, see blog note or http://play.golang.org/p/lH2SzZQEHG

It does not seem to work as expected in C++ either.

dyp
  • 38,334
  • 13
  • 112
  • 177
Øyvind Teig
  • 139
  • 1
  • 9
  • 1
    Related std-discussion mailing: https://groups.google.com/a/isocpp.org/d/topic/std-discussion/pdaoWRp8ZYg/discussion You can find many related questions on StackOverflow by searching for "signed integer overflow undefined behaviour". See also the [`-fwrapv` gcc option](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options) – dyp Sep 12 '15 at 14:17
  • 1
    Very related: http://stackoverflow.com/q/19842215/ – dyp Sep 12 '15 at 14:22
  • 1
    Note that 8-bit operands to `+` are promoted to `int` which is at least 16 bits. @Øyvind, Please, if you don't mind, please describe what are the inputs and outputs of the snippet. "`Cnt2 is 35 if > 0 above`" doesn't make any sense so it's hard to tell what you're looking for. – Potatoswatter Sep 12 '15 at 16:39
  • I don't think the [tag:go] tag should have been added. Everything about this question is C/C++ related and although it might be worth noting in the question that other languages like Go have different behaviour I don't see anything here that would warrant putting this up for all followers/searchers of the Go tag. – Dave C Sep 13 '15 at 16:36
  • (A)(B) Thanks for the refs to other discussions. I will study them. I actually did do some searches in advance (A) -fwrapv did not help on the EDA Playground: http://www.edaplayground.com/x/LSL, for the 8 bit signed case (which is my case) (C) I thought it too long to supply three snippets, but please compile and run with '>', ">=" and "==" below "##", and print Cnt2. (D) I agree not to bring in side cases, however the C/C++ and Go people won't hurt seeing how matters are solved by one other side. That's why I supplied a Go Playground code when I added the Go tag, so it could be verified – Øyvind Teig Sep 13 '15 at 19:48

0 Answers0