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
C++ Catch Blocks - Catch Exception by Value or Reference
Representing 128-Bit Numbers in C++
How to Compile For Os X in Linux or Windows
Will New Return Null in Any Case
What Can Happen If Printf Is Called With a Wrong Format String
Best Compiler Warning Level For C/C++ Compilers
Why Are String Literals L-Value While All Other Literals Are R-Value
Scope Vs. Lifetime of Variable
Same Random Numbers Every Loop Iteration
C++ Implicit Copy Constructor For a Class That Contains Other Objects
Convert a Vector≪Int≫ to a String
C++ Force Std::Cout Flush (Print to Screen)
In Stl Maps, Is It Better to Use Map::Insert Than []
32-Bit to 16-Bit Floating Point Conversion