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

A new Bug

unsigned char aa,bb,cc,dd;

aa = 0xab;
bb = 0xcd;
cc = (aa+bb)%255; //aa+bb=0x178
dd = (unsigned char)((aa+bb)%255);

when debug, youcan see that the result: cc is 0x78, dd is 0x79. In fact, cc and dd should be 0x79.

I debugged in C51 9.60, 9.03. Both had the same output.

I tried in VC2010, TI CCS3.3, both can get the correct result, 0x79.

  • And it is, of course, entirely irelevant which of the multiple tools covered in this forum that bug could be in.  Right.

  • Most "modern" versions of C, would be expected to be 0x78 and not 0x79.

    In your example above, (aa + bb) is equal to 0x78 and not 0x178 as you state.  given that aa + bb is 0x78, 0x78 % 255 is equal to 0x78.

  • You got all of that backwards, I think.

    Modern C would meet the OP's expectations.  Any C compiler respecting any kind of standard, all the way back to K&R1, would have (aa + bb) equal to 0x178, because of standard integer conversion of sub-integer values.   That % 255 is, just as universally, 0x79.  That cast (either implicitly or explicitly) to unsigned char is still 0x79.

    The only versions of C that would get a different result for that are explicitly non-compliant ones, e.g. Keil C51 in its default setting, where it does not apply standard integer conversions.

  • Your logic is good.  That being said, I still expect the Keil C++ compiler (at least the V5 compiler) to generate the answer of 0x78 for what was presented by the OP and not 0x79.  

  • Just tried an online compiler. If the modulo is part of the expression, then it should be promoted to unsigned int before modulo. Therefore 0x178%255 = 0x79.

    Actually I think, one cannot rely on a result of a computation if the size of the variable does not fit. So it is not a bug, no matter if the result is 0x79 or 0x78.

  • The expectation of getting 0x78 is in direct violation of all applicable standards. For both C and C++.  For any standard revision of either of them. Standard integer conversions have been part of C since well before the first C standard.

    I.e. the language does, in fact, guarantee the result in this case, even though it might be less than obvious to the casual reader.  Getting something else can be compiler bug; but that depends on wether the compiler in question was run in a mode that promises to respect the standard(s).  If it promised no such thing, breaking the promise isn't a bug.

  • I debugged in C51 9.60, 9.03. Both had the same output.

    I'm not using C51 today, but there is a checkbox in Target Options somewhere that alters integer promotion. Change it. The cost will be a bit of code size and potentially speed. Broeker I believe is correct regarding the rules of C versus C51. Also you can typecast and/or user intermediate variables of different types to learn what is happening.

  • Thank  you for your reply.

    My code uses parentheses to clearly indicate the operation priority, that is, first operate "aa + bb", then operate modulus 255, and then convert to "unsigned char"。The two lines of code differ only in the last step, I think their output should be the same in this operation as above。

  • Thank  you for your reply.

    My code uses parentheses to clearly indicate the operation priority, that is, first operate "aa + bb", then operate modulus 255, and then convert to "unsigned char"。The two lines of code differ only in the last step, I think their output should be the same in this operation as above。

  • My point wasn't parentheses, but integer promotion (or lack thereof).  Look for the checkbox I mentioned.