Learning embedded C while working in MPLAB X with a PIC24FJ128GB204.
So far, I've mostly heard that you should use unsigned types as much as possible (especially?) on embedded devices, so I've started to use uint8_t arrays to hold strings. However, if I call itoa from stdlib.h, it expects a pointer to a signed char (int8_t) array:
extern char * itoa(char * buf, int val, int base);
This is made specifically clear when I try to compile after using itoa on an unsigned array:
main.c:317:9: warning: pointer targets in passing argument 1 of 'itoa' differ in signedness
c:\program files (x86)\microchip\xc16\v1.36\bin\bin\../..\include/stdlib.h:131:15: note: expected 'char *' but argument is of type 'unsigned char *'
Searching for implementations of itoa on other platforms, that seems to be the common case.
Why is that?
(I've also noticed that most implementations expect value/pointer/radix whereas -for some reason- the stdlib.h from Microchip expects the pointer first. It took me a while to realize this.)
So far, I've mostly heard that you should use unsigned types as much as possible (especially?) on embedded devices
This is true mainly for the reason that (accidentally or intentionally) signed operands mixed with the bitwise operators create havoc. But also there aren't many cases in low level programming where you actually need to use signed types.
For example, MISRA-C enforces you to always use unsigned variables, operands and integer constant unless the intention is to actually use a signed type. So this isn't just something opinion-based, MISRA-C is de facto industry standard for most professional embedded systems.
so I've started to use uint8_t arrays to hold strings
That's ok but it isn't wrong to use char
for that purpose either. The only time when it is ok to use char
is when you intend to store text. Note that char
is especially nasty, because unlike all other types in the language, it has unknown signedness. Each compiler can make char
either signed or unsigned and still conform with the C standard. So code relying on char
being either signed or unsigned is broken. However, for text strings this doesn't matter since they are always positive.
However, if I call itoa from stdlib.h, it expects a pointer to a signed char (int8_t) array:
Your compiler apparently treats char
as signed then. First of all please note that itoa
isn't standard C and isn't allowed to exist inside stdlib.h
when strict C standard conformance is desired. But more importantly, different compilers might implement the function differently since it isn't standardized.
As it turns out, you can safely cast wildly between the various character types: char
, unsigned char
, signed char
, int8_t
and uint8_t
(the stdint.h 8 bit types are pretty much dead certain to be character types even though the standard doesn't say so explicitly). The character types specifically have various special rules associated with them, meaning that you can always cast something to a character type.
You can safely cast your uint8_t
array to a char*
, as long as there are no qualifiers (const
etc) present.