Conversion between uint8 and char in C
Solution 1
Both types are 8bits long. The difference comes with signedness.
- The
uint8
type is unsigned. - The
char
type should be signed in your case. Actually, it is compiler dependent, but most compilers consider thechar
type as signed by default and have an option to forcechar
type as unsigned if needed. See the C99 standard document reference §6.2.5p15:
The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.
CHAR_MIN, defined in limits.h, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options.
Solution 2
char
and uint8
have both something in common, and that's important: they're both 8 bits integers. Now two questions
- is/are this/these 8 bits integer(s) signed, or unsigned?
And more importantly
- does it matter in your case?
I.e. do you want to send to the function an array made of integers for which it is important to have them considered signed? For instance, if the function would do something like that,
if (charvalue < 0) { ...
or if you want the function to pay attention to the signedness of the bytes (if that'd be possible) ; if the function would do that, and sign would matter: sending a 255
is positive, but considering the byte signed, that'd be interpreted as -1
...
But that doesn't make sense since the function takes uint8 *
(actually inside the function the devs may have used char
to treat bytes individually, and use their signedness, but in this case having a function signature like that would be very misleading!)
So the E2PROM is treating bytes unsigned, and you can safely cast the pointer given to the function to remove the warning,
CyBle_StoreAppData((uint8 *)Prefix,datastack_ROM,10,0);
or simply
uint8 Prefix[10];
if that doesn't cause other problems/warning with the rest of your code.
Solution 3
uint8 Container_ID[10];
Thats an unsigned 8 bit integer with possible values from 0
to 255
char Prefix[10];
In your case a signed 8 bit char with integer values from -127
to +128
Because they are not the same sign type, you get a conversion warning, as you should.
Related videos on Youtube
abdullah cinar
Updated on September 15, 2022Comments
-
abdullah cinar almost 2 years
I have an API that implements a writing operation to EEPROM. Here is its declaration:
CYBLE_API_RESULT_T CyBle_StoreAppData (uint8 * srcBuff, const uint8 destAddr[], uint32 buffLen, uint8 isForceWrite);
It is working well when I call this function and send an array parameter to
srcBuff
which has been declared asuint8
type.The problem is, I need to send
char
array pointer to it. I was thinking thatchar
is already auint8
, but I get a compiler warning if I send achar
array pointer to that function instead ofuint8
. Why can't I usechar
instead ofuint8
? Here are 2 examples of calling that function:static const uint8 datastack_ROM[dedicatedRomSize] = {0}; uint8 Container_ID[10]; char Prefix[10]; //Call the function with Container_ID which has been declared as uint8. This is working. CyBle_StoreAppData(Container_ID,datastack_ROM,10,0); //Call the function with Prefix which has been declared as char. This is NOT working. CyBle_StoreAppData(Prefix,datastack_ROM,10,0);
Here is the warning for the second call:
passing char[10] to parameter of type 'uint8 *' converts between pointers to integer types with different sign.
Aren't
char
anduint8
same? -
abdullah cinar over 8 yearsI didn't think that it is compiler dependent. I had found this link link. But if i declare the
Container_ID
as unsigned, i can not use string function which i use them for another job. So i should cast it like at the @Joachim's answer right? -
abdullah cinar over 8 yearsI didn't think that it is compiler dependent. I had found this link link. But if i declare the
Container_ID
as unsigned, i can not use string function which i use them for another job. So i should cast it like at the @Joachim's answer right? -
2501 over 8 years@abdullahcinar Yes you can cast it, assuming your architecture has 8 bits per byte and two's complement, which is almost certain it does.
-
abdullah cinar over 8 yearsYes, i checked it and it's true. So i can continue with that. Thanks a lot to all of you who have an answer for this question.
-
greydet over 8 yearsSee my edit, I added a reference to the C standard. But yes you could cast it as proposed.
-
plugwash over 8 yearsI'm pretty sure gcc gives the "differe in signedness" conversion warning in this case even on platforms where char is unsigned.
-
2501 over 8 years@plugwash No I can quote you the standard on that. char is literally identical to either signed char or unsigned char, except it is it's own type. (Please don't downvote based on subjective feelings towards me. Yesterday I was only trying to help you and made a mistake, you can check the comments, where I apologized for my error.)
-
abdullah cinar over 8 yearsThank you :) This was explanatory. I confirmed that my compiler had considered that as signed. So i have used a cast operation and it is working very well. Thank you all.
-
M.M over 8 years@abdullahcinar your link only refers to a particular compiler and platform. It's normal for ARM targets to default plain char to unsigned. Since there are more ARM CPUs than PCs in the world, perhaps it is more correct to say that
char
is usually unsigned ! -
2501 over 8 years@plugwash I have just checked with gcc 5.1.0 with -Wall -Wextra -Wconversion and it doesn't give a warning when the signedness of char and int8_t match, and it gives an error when they don't match as per my answer. So that is a practical example. The theoretical aspect is explained in: C11 6.2.5., pt 15. I think that addresses you concern as invalid.