When Is Uint8_T ≠ Unsigned Char

When is uint8_t ≠ unsigned char?

If it exists, uint8_t must always have the same width as unsigned char. However, it need not be the same type; it may be a distinct extended integer type. It also need not have the same representation as unsigned char; for instance, the bits could be interpreted in the opposite order. This is a silly example, but it makes more sense for int8_t, where signed char might be ones complement or sign-magnitude while int8_t is required to be twos complement.

One further "advantage" of using a non-char extended integer type for uint8_t even on "normal" systems is C's aliasing rules. Character types are allowed to alias anything, which prevents the compiler from heavily optimizing functions that use both character pointers and pointers to other types, unless the restrict keyword has been applied well. However, even if uint8_t has the exact same size and representation as unsigned char, if the implementation made it a distinct, non-character type, the aliasing rules would not apply to it, and the compiler could assume that objects of types uint8_t and int, for example, can never alias.

uint8_t vs unsigned char

It documents your intent - you will be storing small numbers, rather than a character.

Also it looks nicer if you're using other typedefs such as uint16_t or int32_t.

Difference between uint8_t and unsigned char

I'm using mplabX 4.20, and xc8 compiler. I'm trying to understand
which is the difference between uint8_t and unsigned char. Both of
them have size from 0 till 255. Both of can hold characters and
numbers. But which is better to use, and for which case?

unsigned char is the unsigned integer type corresponding to signed char. Its representation does not use any padding bits. Both of these occupy the same amount of storage as type char, which is at least 8 bits, but may be more. The macro CHAR_BIT tells you how many it comprises in your implementation. Every conforming C implementation provides all of these types.

uint8_t, if available, is an unsigned integer data type exactly 8 bits wide and with no padding bits. On an implementation having CHAR_BIT defined as 8, this is the same type as unsigned char. On such systems you may use the two types interchangeably wherever the declarations provided by stdint.h are in scope. On other systems, uint8_t will not be declared at all.

Example if i want to create a buffer for holding a string.

If you want to declare a buffer for holding a string then as a matter of style, you should use type char, not either of the other two:

char buffer[20] = "Hello World";

Although either of the other two, or signed char, can also be used for string data (provided in the case of uint8_t that the type is defined at all), type char is the conventional one to use for character data. Witness, for example, that that's the type in terms of which all the string.h functions are declared.

You should use uint8_t where and only where you need an integer type with exactly its properties: unsigned, 8 value bits, no padding bits.

You should use unsigned char where you want the smallest unsigned integer type available, but you don't care whether it is exactly 8 bits wide, or where you want to emphasize that it is the same size as a char -- the smallest discrete unit of storage available.

You should use signed char where you want the smallest signed integer type available but don't care about the exact size or representation.

You should use int8_t where you want a signed integer type with exactly 7 value bits, one sign bit, and no padding bits, expressed in two's complement representation.

You should remain mindful that uint8_t and int8_t are not guaranteed to be available from every C implementation, and that where they are available, their use requires inclusion of stdint.h. Furthermore, this header and these types were not part of C90 at all, so you should not use them if compatibility with legacy C implementations is important to you.

How to check if uint8_t exists as a type, instead of unsigned char?

There are a few different ways to deal with this. In an open source project that needs to be portable, the common solution is to have a "configure script", which is run to setup the build system. It would then have something like HAVE_UINTX_TYPES that is set or not set in some config.h or similar [which was one of the results of the "configure script", and do something like this:

#include "config.h"
...
#ifndef HAVE_UINTX_TYPES
#include "uintx_types.h"
#endif

In a less "needs to run on almost anything" system, you could solve the same problem by simply have a -DHAVE_UINTX_TYPES as part of the flags to the compiler. And since you (presumably) have some part of the build system that sets different compile options, picks a different compiler, etc, for the two different builds, this shouldn't be a big issue to add.

And assuming that you are happy that your unsigned char is indeed 8 bits, you could also do have a uintx_types.h that contains something like this:

typedef unsigned char  uint8_t; 
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;

Another option is to not use uint8_t and uint16_t etc directly, but have your own definitions [and have these depend on the appropriate build setting for "is it ARM or Renesas", e.g. by using different include options]:

ARM/types.h:

typedef unsigned char  u_int8;
typedef unsigned short u_int16;
typedef unsigned int u_int32;

Renesas/types.h:

typedef unsigned char  u_int8;
typedef unsigned int u_int16;
typedef unsigned long u_int32;

Converting 'uint8_t' 'float' and 'unsigned char' into 'char' for LCD display

snprintf() is the answer!

Thank you all

error: cast from ‘uint8_t* {aka unsigned char*}’ to ‘unsigned int’ loses precision [-fpermissive]

Using the online-compiler you provided and changing this line

cout<<hex<<unsigned(ptr)<<endl;

to

cout << hex << (uintptr_t) ptr << std::endl;

prints the addresses.

When checking the size of these datatypes using:

std::cout << "sizeof(uintptr_t) = " << sizeof(uintptr_t) << std::endl;
std::cout << "sizeof(unsigned int) = " << sizeof(uint8_t*) << std::endl;
std::cout << "sizeof(unsigned int) = " << sizeof(unsigned int) << std::endl;

the output is:

sizeof(uintptr_t) = 8
sizeof(uint8_t*) = 8
sizeof(unsigned int) = 4

The pointer-size is 8 byte while your unsigned int type has only a size of 4 bytes. That's why this error appears. The upper 8 byte are cut off and the address wouldn't be correct.



Related Topics



Leave a reply



Submit