Compiler Error unsigned char test

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Compiler Error unsigned char test

1,055 Views
Richly
Contributor III

Compiler incorrectly identifies test as "always true" even when it shouldn't and compiles incorrect code. See sample

code below.  Note that the variables a and b are unsigned chars, which appears to be the source of the problem, while c and d  are signed chars and are treated correctly.


If you look at the generated code, you'll see that there is no test generated for (a != ~b) but there is for (c != d).

Also (ANOTHER CW10.6 BUG), if I try to single step (F6) through the code, the debugger fails (hangs) at the (a != ~b) line

unless I put it into "Instruction Stepping Mode".


At the end of running, error should be 0, but it's 1.


Obviously, this code snippet is uninteresting...the original in my software involved reading values from FRAM to test whether they really were complements of each other.


I've reported this bug as a "service request" to Freescale.

 

CodeWarrior for MCU

Version: 10.6

Build Id:140329


========== SAMPLE CODE ==========

int error;

char m[2] = {0, ~0};

unsigned char fn(unsigned char k) {

return m[k];

}

 

void compilerError(void) {

    // variables are declared volatile so the debugger shows them.

    volatile unsigned char a, b;

    volatile signed char c, d;

 

    // m is initialized here, because I've turned off auto initialization

    m[0] = 0;

    m[1] = ~0;

    error = 0;

 

    a = fn(0);

    b = fn(1);

    if (a != ~b) // incorrectly marked "Condition always TRUE"

        error |= 1;

 

    c = fn(0);

    d = fn(1);

    if (c != ~d)

        error |= 2;

}   // at this point, error should be 0 but is 1

Labels (1)
Tags (3)
0 Kudos
3 Replies

750 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

unsigned char b = ~0;

and ~b is 0xffffff00;

so    if (a != ~b) is true .

Here need cast convert :


  if (a != (unsigned char) ~b)

Best Regards,

Alice

------------------------------------------------------------------------------------------

If this post answers your question, please click the Correct Answer button.

-----------------------------------------------------------------------------------

If this post help your question, please click the helpful Answer button.

749 Views
Richly
Contributor III

Thanks to both of you. After reading your responses, I looked at the ANSI C standard -- hardly light reading!  The issue is that any operation performed on a char value requires it be promoted to an int.

As an unsigned char, b = ~0 means b = 0xff.  Promotion to an int must follow the rule, "The integral promotions preserve value including sign." As far as I can tell, for my configuration of the compiler, an int is 16-bits, so it was unclear to me (aren't standards fun!) whether this means that ~b should be 0x00ff or 0xffff after it's promoted.  As an old assembly language programmer, I expected the latter ("sign extension"), since I think of unsigned char as simply a bit pattern, and 0xffff preserves the sign. However, as an unsigned value, 0xff is 255, but 0xffff is 65535, certainly not the same value. From the observed behavior, I have to accept that my expectation was wrong.

Live and learn!

Thanks again!

0 Kudos

749 Views
StenS
Contributor III

I see this same behavior on classic CW for S12(x) v. 5.1. I think it is due to the ANSI C rule that an unsigned char is converted to int before performing an unary operation. By casting the type of ~b back to unsigned char it does work:

   if (a != (unsigned char) ~b) ...

Sten