This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Arithmetic using numeric constants

Hello,

We came across a mystery/bug yesterday. This was tested with C51 v9.53 (Simplicity Studio) and 9.56 (uVision).

unsigned char data c;
unsigned int data d;

// The values 0x7B and 0xFF7B are wrong
c = (200 - 50) * (255 - 0) / (255 - 50);
0000738d:   MOV     65H, #7BH

d = (200 - 50) * (255 - 0) / (255 - 50);
00007390:   MOV     66H, #0FFH
00007393:   MOV     67H, #7BH


//These are correct
c = (200 - 50) * (255u - 0) / (255 - 50);
0000738d:   MOV     65H, #0BAH

d = (200 - 50) * (255u - 0) / (255 - 50);
00007390:   MOV     66H, #00H
00007393:   MOV     67H, #0BAH

The uVision docs say that numeric constants default to 16 bits. Is this not true? Or is this an issue with the "Constant Folding" optimizing step?

Any insights appreciated,
Darren

Parents
  • K&R is not really used as a spec by compilers anymore.
    While correct, that is irrelevant for the case at hand, because this aspect hasn't changed since K&R 2nd edition, 1988, which still accurately reflects the current international standard in these aspects.

    Hexadecimal constants are always unsigned (without suffix).
    No, they're not. It used to be like that back when K&R 1st edition was the only de-facto standard, but it has been wrong for 27 years now. The type of 0xff is signed int. Yes, that may be surprising.

    Decimal constants are always sign integer (without suffix). They will not be upgraded to unsigned constants.
    Depending on what kind of "being upgraded" you refer to here, that's wrong in one of two ways.

    Decimal, unsuffixed constants have signed type, correct. But there is no "upgrading" of constants involved in getting that type. They get a type big enough for their value, and that's that.

    But constants, like any other integer operand, will be upgraded (the correct term is: "implicitly converted") to unsigned if they appear in expression contexts like the ones described in this threads.

    Hans-Bernhard Broker correctly pointed this out earlier, referencing a more recent spec than K&R.
    That statement is misleading, because this discussion hasn't touched any difference between K&R1 and ANSI/ISO standard C except your mention of the type of hex constants.

Reply
  • K&R is not really used as a spec by compilers anymore.
    While correct, that is irrelevant for the case at hand, because this aspect hasn't changed since K&R 2nd edition, 1988, which still accurately reflects the current international standard in these aspects.

    Hexadecimal constants are always unsigned (without suffix).
    No, they're not. It used to be like that back when K&R 1st edition was the only de-facto standard, but it has been wrong for 27 years now. The type of 0xff is signed int. Yes, that may be surprising.

    Decimal constants are always sign integer (without suffix). They will not be upgraded to unsigned constants.
    Depending on what kind of "being upgraded" you refer to here, that's wrong in one of two ways.

    Decimal, unsuffixed constants have signed type, correct. But there is no "upgrading" of constants involved in getting that type. They get a type big enough for their value, and that's that.

    But constants, like any other integer operand, will be upgraded (the correct term is: "implicitly converted") to unsigned if they appear in expression contexts like the ones described in this threads.

    Hans-Bernhard Broker correctly pointed this out earlier, referencing a more recent spec than K&R.
    That statement is misleading, because this discussion hasn't touched any difference between K&R1 and ANSI/ISO standard C except your mention of the type of hex constants.

Children
No data