CW 6.1 for MCF51AC256: Why do bitwise operations default to an INT result?

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

CW 6.1 for MCF51AC256: Why do bitwise operations default to an INT result?

2,748 Views
Kopone
Contributor IV
Hello,

I am currently porting C code to the 51AC256.
I get plenty of warnings about "implicit conversions from int to unsigned  char" in cases like this:

----
unsigned char a, b;
...
a=b & 0x0f;
----

Just assigning "a=0x0f" causes no warning, so it is not the constant but the result of the bitwise AND, that is treated as an integer by the compiler. However to my understanding of C this should not be the case, instead it should default to the common operands type. So since both are unsigned char, the result should be as well.

Besides working over all the code like "a=(unsigned char)b & 0x0f", is there any option I could turn on/off to have the compiler think of the result's type as a type matching the operands?

I know I could turn off the warnings, however this is not an option since I'd lose the serious warnings as well.

Regards,
 Sven

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

562 Views
Kopone
Contributor IV
Why, thanks for clearing that up. I checked my K&R meanwhile and it just told me so. Always thought the compiler would look for the least common denominator.

Wonder how that never got me any warnings in the last decades...might just be that some compilers are a bit less..."picky" or whatever you might call it. Speaking of which...I do not get any warning when I set the target CPU to a S08. Seems the compiler puts the math in a 8 Bit register when possible.

I'll have to do the typecasts then since I dont want to miss possible similar warnings.

Regards,
 Sven
0 Kudos

562 Views
Lundin
Senior Contributor IV
Check out the "integer promotions" in C. These are rather subtle implicit conversions that you must be aware of. All integer types smaller than "int" are always implicitly converted to int before a calculation is done. Since int can be either signed or unsigned, you can get a whole lot of bugs from this. This is a rule in ISO C, it doesn't matter which platform you have.

Explicit typecasts are always good.

Message Edited by Lundin on 2008-08-21 02:28 PM
0 Kudos

562 Views
Kopone
Contributor IV
Thanks for the input. I really thought (up until now) the compiler would stick with 8 bit if there was no explicit int (or larger) in an expression...probably since I never ran into any similar warnings before.
But then, I really think it's a compiler dependant thing - be it ISO, ANSI or whatever. Not even gcc does care - nor CodeWarrior for the S08 as mentioned above.
I may have used about ten different C compilers so far (for Atari, Apple (that was CodeWarrior too), Linux, Windows and some MCUs) and I am pretty sure there were similar expressions in all of my programs, but no warnings. Maybe for some of the compilers it is part of a per default disabled option like "use strict ANSI c". I mean, frankly, if you have

unsigned char a, b, c

and you go

a=b+c;

and you get a warning...it doesn't make much sense now does it? Ok, according to the promotion rules it does, but why promote anything if there aint no reason. Now what I wonder...do all the non-complaining compilers actually promote b and c to int and then silently convert the result back to unsigned char...or will they produce plain 8 bit code right away, which obviously would make much more sense. In other words, do they all just ignore the promotion rules in this case?

Ed: I just tried and the answer for the S08 compiler is, that it silently produces plain 8 bit code.

Regards,
 Sven


Message Edited by Kopone on 2008-08-22 11:13 PM
0 Kudos

562 Views
Lundin
Senior Contributor IV
Yes, every compiler promotes those operands or it doesn't conform to ISO C. Try to run this code on any C compiler and you will see for yourself:

unsigned char x, y;
printf("%d", sizeof(x+y));

However, the compiler may of course optimize the code how much it wants as long as it doesn't change the meaning of it. This is the case in your S08 example.

The reason you get a warning on Codewarrior is because it is more picky than other compilers, which is a good thing. An embedded compiler needs to be extra aware of things like implicit typecasts, since the code is much more likely to be ported, as well as more likely to steer safety-critical applications, compared to for example code written for a PC.

And yes, the integer promotion rules are quite illogical, just as the rest of the C language. But they exist for a reason, consider this situation:

unsigned char x = 255;
unsighed char y = 255;

if( (x+y) > 255)
{
  /* do something */
}


Because of the integer promotion rules, the expression is evaluated correctly. If there was no promotion, x+y would have been 254 and the program wouldn't work as expected.

Message Edited by Lundin on 2008-08-25 12:48 PM
0 Kudos

562 Views
Kopone
Contributor IV
Interesting. I always thought of C as some kind of macro assembler and as such it always seemed pretty logical to me. The only thing I never really liked was the not-so-total-control of memory when you use ints and longs on different machines, not really knowing how many bits they'll use up, as well as the padding of bits and bytes in structs. This sometimes turned into little problems for me, when things had to be optimized for speed and thus e.g. pointers to long were used to copy a block of memory (where actually a collection of structs was residing).
Really never knew the result of an expression could exceed it's operands value range, hence I would of course never do a comparison as in your example, instead use integers right away if I'd expect anything > 255 anywhere.
So, the only thing I would have expected here was a warning like "Expression is always false" :smileywink:

Well, learn something new every day.

Thanks for the input,
 Sven
0 Kudos

562 Views
CompilerGuru
NXP Employee
NXP Employee
The difference in the different tools is not in the behavior of the generated tools, its "only" in the warnings they generate. And there will be always tools being more picky of certain things, in this case the CF compiler is technically correct, but for in my personal opinion this particular warning distracts more than it helps, especially for the and with a constant where the result never overflows (this does not affect the type as defined by ANSI though).

Daniel
0 Kudos

562 Views
CrasyCat
Specialist III
Hello
According to the ANSI C standard compiler is performing integral promotion before performing any operation on a char variable.
That means the 2 operators are sign-extended to an int and the operation is performed on an int.
Only solution to prevent the warning:
  1- Explicitly cast the result to an unsigned char
           a=(unsigned char)(b & 0x0f);
  2- Enclose the function where you have the code between
     #pragma warn_implicitconv off  and   #pragma warn_implicitconv  on
   
Alternatively you can des-activate the option "Implicit Arithmetic Conversion" in the "C/C++ Warning" Panel
CrasyCat
0 Kudos