implicit signed to unsigned conversion

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Hi guys

I am using XC8 free compiler from Microchip, v1.45.

When I do this, it gave me warning: jumper.c:54: warning: (373) implicit signed to unsigned conversion
Code:
uint8_t mask = 0;
// do some stuff to mask
LATF = ~mask;
When I do this, it won't complain:
Code:
uint8_t mask = 0;
// do some stuff to mask
LATF = (uint8_t)(~mask);
Why?
 

nsaspook

Joined Aug 27, 2009
13,262
Ignore it or change the warming level to something like -2 if you know the code is correct. XC8 integer promotion noise. Both are promoted to "int" by the operator, thus the result is signed.
 

WBahn

Joined Mar 31, 2012
30,045
I don't recommend changing the warning level because here is what will invariably happen sooner or later. Instead of putting in the appropriate casts so that the compiler knows that you mean to do what is happening, you change the warning level because "you know the code is correct". But that suppresses the warnings everywhere you have this kind of implicit conversion (plus whatever other warnings are suppressed) and then elsewhere in the code you have an implicit conversion that matters and that you needed to deal with differently, but you don't catch it because you've suppressed the warnings that the compiler otherwise would have smacked you upside the head with.
 

nsaspook

Joined Aug 27, 2009
13,262
I don't recommend changing the warning level because here is what will invariably happen sooner or later. Instead of putting in the appropriate casts so that the compiler knows that you mean to do what is happening, you change the warning level because "you know the code is correct". But that suppresses the warnings everywhere you have this kind of implicit conversion (plus whatever other warnings are suppressed) and then elsewhere in the code you have an implicit conversion that matters and that you needed to deal with differently, but you don't catch it because you've suppressed the warnings that the compiler otherwise would have smacked you upside the head with.
I agree with you but it's frivolous to add bogus casts to correct code.
This 'warning' is a ANSI 16-bit integer promotion artifact on 8 bit hardware that until recently was silent on the compiler at default -3.
"(XC8E-109) The warning level for warning 373 (implicit signed to unsigned conversion) has been raised from -4 to -3." The default level is -3 so now you see it.
It generates the correct code.
http://www.microchip.com/forums/m/tm.aspx?m=1015872

Warning levels and messages
http://www.microchip.com/forums/download.axd?file=0;926620
 

WBahn

Joined Mar 31, 2012
30,045
If you are comfortable enough with the warning levels of the compiler you are using to be confident that the warnings issued at a certain level can never reveal a logic error, then by all means suppress them.
 

nsaspook

Joined Aug 27, 2009
13,262
More detail:
http://ww1.microchip.com/downloads/en/DeviceDoc/50002053G.pdf
The consequence of integral promotion as illustrated above is that operations are not performed with char -type operands, but with int -type operands. However, there are circumstances when the result of an operation is identical regardless of whether the operands are of type char or int. In these cases, the compiler will not perform the integral promotion so as to increase the code efficiency. Consider this example. unsigned char a, b, c; a = b + c; Strictly speaking, this statement requires that the values of b and c should be promoted to unsigned int, the addition performed, the result of the addition cast to the type of a, and then the assignment can take place. Even if the result of the unsigned int addition of the promoted values of b and c was different to the result of the unsigned char addition of these values without promotion, after the unsigned int result was converted back to unsigned char, the final result would be the same. If an 8-bit addition is more efficient than a 16-bit addition, the compiler will encode the former.
For some reason they are now warning on when it decides, correctly, to do 8-bit math on a 8-bit machine.

https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules
Integer Promotions
Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators. The following code fragment shows the application of integer promotions:

Noncompliant Code Example
This noncompliant code example demonstrates how performing bitwise operations on integer types smaller than int may have unexpected results:

uint8_t port = 0x5a;
uint8_t result_8 = ( ~port ) >> 4;
In this example, a bitwise complement of port is first computed and then shifted 4 bits to the right. If both of these operations are performed on an 8-bit unsigned integer, then result_8 will have the value 0x0a. However, port is first promoted to a signed int, with the following results (on a typical architecture where type int is 32 bits wide):

It's murky area with 8 bit hardware, the old C18 didn't do integer promotions (with rants from non-embedded programmers who didn't understand why you sometimes need strict 8-bit math on 8-bit unsigned variables to optimize code to ASM speeds in C) and with XC8 the compiler will always use integral promotion and there is no way to disable this .

With a 16 or greater bit machine (C standard is not written with 8 bit machines in mind) these warning are totally valid in most cases but XC8 does the right thing (or it would be a dog of a C compiler) without the casts because the target hardware is 8 bits.

https://barrgroup.com/Embedded-Systems/How-To/Efficient-C-Code
Integer promotion
The integer promotion rules of ANSI C are probably the most heinous crime committed against those of us who labor in the 8-bit world. I have no doubt that the standard is quite detailed in this area. However, the two most important rules in practice are the following:
ANSI C
The first step to writing a realistic C program for an 8-bit computer is to dispense with the concept of writing 100% ANSI code. This concession is necessary because I don't believe it's possible, or even desirable, to write 100% ANSI code for any embedded system, particularly for 8-bit systems.

Some characteristics of 8-bit systems that prevent ANSI compliance are:

  • Embedded software interacts with hardware, yet ANSI C provides extremely crude tools for addressing registers at fixed memory locations
  • All nontrivial systems use interrupts, yet ANSI C doesn't have a standard way of coding interrupt service routines
  • ANSI C has various type promotion rules that are absolute performance killers on an 8-bit computer
  • Many older microcontrollers feature multiple memory banks, which have to be hardware swapped in order to correctly address the desired variable
  • Many microcontrollers have no hardware support for C's stack (i.e., they lack a stack pointer)
 
Top