• AVR Freaks

Hot!XC8 type promotions

Author
kadv
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/12/01 23:12:06
  • Location: 0
  • Status: offline
2021/01/19 00:54:40 (permalink)
0

XC8 type promotions

Hi all. I'm not sure if I'm expecting the unexpected or if XC8 is being silly. This does not work:
uint8_t foo = 75;
uint16_t bar = 1800;
uint32_t foobar = (bar * foo);
 This does:
uint8_t foo = 75;
uint16_t bar = 1800;
uint32_t foobar = bar;
foobar *= foo;
 In the former I see foobar truncated at 16bits. I would have expected an automatic type promotion in the operands to uint32_t.  Is my expectation justified?
post edited by kadv - 2021/01/19 02:27:38
#1

12 Replies Related Threads

    ric
    Super Member
    • Total Posts : 29861
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: XC8 type promotions 2021/01/19 02:04:18 (permalink)
    +3 (3)
    kadv
    In the former I see fooarg truncated at 16bits. I would have expected an automatic type promotion in the operands to uint32_t.  Is my expectation justified?

    Your expectation is wrong.
    Standard C rules are that the calculation is done using the largest type of the operands, with no reference at all made to what sort of variable the result will be stored in.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    mbrowning
    USNA79
    • Total Posts : 1874
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: XC8 type promotions 2021/01/19 02:21:18 (permalink)
    +2 (2)
    No. XC8 promotes according to standard which is not what you are expecting. You may be used to C on PCs or 32b micros where an int is 32b (or larger).
    Math is done without regard to the variable type on the left side of =. Since the largest type on the right is 16b you get a 16b result. If the largest type on the right is smaller than int (16b for XC8) it gets promoted to int. The truncation is expected.
    Cast one var on right to uint32 if you need a 32b result.
    I am not expert on the rules but some on these forums are and hopefully will chime in if I’ve missed something important

    I see ric beat me to it. He is one of those experts
    post edited by mbrowning - 2021/01/19 02:23:52
    #3
    kadv
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2019/12/01 23:12:06
    • Location: 0
    • Status: offline
    Re: XC8 type promotions 2021/01/19 02:23:45 (permalink)
    0
    Fair enough. Thank you.

    Do you have a reference? Prior to starting the post I did a quick search - found this: https://www.eskimo.com/~scs/cclass/int/sx4cb.html - did not have K&R with me to ascertain. See point 7.
    #4
    mbrowning
    USNA79
    • Total Posts : 1874
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: XC8 type promotions 2021/01/19 02:27:38 (permalink)
    +1 (1)
    Point 1 applies, since int (and short) are 16b
    #5
    ric
    Super Member
    • Total Posts : 29861
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: XC8 type promotions 2021/01/19 02:30:55 (permalink)
    +2 (2)
    That description is ok.
    Note, point 7 applies AFTER the calculation has been done, not before.
    It just describes how to cram the result of the calculation into the result variable.
    If the calculation was done using 16 bit math, and overflowed, it's too late to get the extra bits back.
    post edited by ric - 2021/01/19 02:31:59

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    du00000001
    Just Some Member
    • Total Posts : 4114
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: XC8 type promotions 2021/01/19 02:32:34 (permalink)
    +2 (2)
    kadv
    Fair enough. Thank you.

    Do you have a reference? Prior to starting the post I did a quick search - found this: https://www.eskimo.com/~scs/cclass/int/sx4cb.html - did not have K&R with me to ascertain. See point 7.



    Point 7 applies: when the (truncated) product has been calculated, it is converted to uint32_t during assertion to foobar. But the damage has already been done prior this.

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #7
    kadv
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2019/12/01 23:12:06
    • Location: 0
    • Status: offline
    Re: XC8 type promotions 2021/01/19 02:35:25 (permalink)
    0
    Thank you.
    #8
    1and0
    Access is Denied
    • Total Posts : 12080
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: XC8 type promotions 2021/01/19 03:26:18 (permalink)
    +2 (2)
    kadv
    This does not work:
    uint8_t foo = 75;
    uint16_t bar = 1800;
    uint32_t foobar = (bar * foo);


    Points 1, 6, and 7 from that link apply to your expression in Post #1.
    • (1) uint8_t foo is promoted to an int16_t.
    • (6) Now the expression has both signed (int16_t foo) and unsigned (uint16_t bar). Both are of the same rank, so the signed type is converted to the unsigned type; i.e. foo is converted to uint16_t.
    • The calculation is performed as uint16_t * uint16_t with an uint16_t result. That is, 75u * 1800u = 3928u, not 135000.
    • (7) The assignment operator = converts the uint16_t result to the type on the left side which is uint32_t, so foobar = 3928uL.
    #9
    mlp
    boots too small
    • Total Posts : 1005
    • Reward points : 0
    • Joined: 2012/09/10 15:12:07
    • Location: previously Microchip XC8 team
    • Status: offline
    Re: XC8 type promotions 2021/01/21 19:09:20 (permalink)
    +1 (1)
    kadv
    I did a quick search - found this: https://www.eskimo.com/~scs/cclass/int/sx4cb.html

    Trust Steve Summit - he knows of what he writes. If you want to learn the C language, read all his course notes and do the assignments.
    did not have K&R with me

    Remember also that K&R2 covers C89 a.k.a. C90 only.
    C99 renders some of that inaccurate.
     
    But when it comes to integer promotions the rules have remained unchanged since 1989 except for the (mistaken, IMnsHO) addition of long long in 1999.

    Mark (this opinion available for hire)
    #10
    Murton Pike Systems
    Super Member
    • Total Posts : 223
    • Reward points : 0
    • Joined: 2020/09/10 02:13:01
    • Location: 0
    • Status: online
    Re: XC8 type promotions 2021/01/22 20:24:24 (permalink)
    0
    This is where C can fall down a bit doing something unexpected but still following spec.
    Also a side effect of mixing types.
    I do a lot of PC programming and generally try to keep the types the same 32 bits to avoid such complications.
    Of course with the PC you dont get the restrictive memory sizes you do on the smaller  PIC's.
    Just another trip on the road to learning C.
     
    I did on my pc and it resulted in not a byte output but at least 16 bits. Answer was 256.

     
    byte ax=255;
    byte axx=1;
     
    System.Windows.Forms.MessageBox.Show(Convert.ToString(ax + axx));
     
     

     
    post edited by Murton Pike Systems - 2021/01/22 20:31:34
    #11
    1and0
    Access is Denied
    • Total Posts : 12080
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: XC8 type promotions 2021/01/22 20:52:49 (permalink)
    0
    nigelwright7558
    I did on my pc and it resulted in not a byte output but at least 16 bits. Answer was 256.

    byte ax=255;
    byte axx=1;
     
    System.Windows.Forms.MessageBox.Show(Convert.ToString(ax + axx));


    You don't need a PC to do that. ;)  XC8 will do:
    volatile uint8_t ax = 255;
    volatile uint8_t axx = 1;
    volatile uint16_t foo;

    void main(void) {
        foo = ax + axx;  // = 256 too
        while(1);
    }

     
    #12
    ric
    Super Member
    • Total Posts : 29861
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: XC8 type promotions 2021/01/22 21:24:24 (permalink)
    +1 (1)
    nigelwright7558
    This is where C can fall down a bit doing something unexpected but still following spec.

    Only if you don't pay attention to the spec.
    I find that coming from PIC assembly, the rules make sense.
    The people coming unstuck have often been using basic, which is far more forgiving (and less efficient), by promoting eveything to a size big enough to fit in the result variable.
     

    I did on my pc and it resulted in not a byte output but at least 16 bits. Answer was 256.
    byte ax=255;
    byte axx=1;
    System.Windows.Forms.MessageBox.Show(Convert.ToString(ax + axx));

    That is perfectly in line with the C spec. It's a feature called "integer promotion", which states that calculations are done using AT LEAST the size of an "int" variables.
    mbrowning mentioned this in post#3.
    post edited by ric - 2021/01/23 00:51:58

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #13
    Jump to:
    © 2021 APG vNext Commercial Version 4.5