abdullah cinar February 2016

Conversion between uint8 and char in C

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 as uint8 type.

The problem is, I need to send char array pointer to it. I was thinking that char is already a uint8, but I get a compiler warning if I send a char array pointer to that function instead of uint8. Why can't I use char instead of uint8 ? 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 and uint8 same?

Answers


2501 February 2016

uint8_t is very likely defined as an unsigned char.

char is it's own type that behaves either exactly like signed char or unsigned char (Note, those are three distinct types).

In this case it behaves like signed char, and you get a conversion warning.


greydet February 2016

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 the char type as signed by default and have an option to force char 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.


Magisch February 2016

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.


Giorgi Moniava February 2016

As highlighted in this answer mixing arguments like that is constraint violation.

You're passing an unsigned char* argument to a function that expects a char* argument. The two types are not compatible, and there is no implicit conversion from one to the other. A conforming compiler may issue a warning (that counts as a diagnostic) and then proceed to generate an executable, but the behavior of that executable is undefined.

Although that answer is for char* vs unsigned char* I believe same should hold with char*, uint8_t*.


ringø February 2016

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.

Post Status

Asked in February 2016
Viewed 3,808 times
Voted 10
Answered 5 times

Search




Leave an answer