The casts char <=> uint8
are fine. It is always allowed to access any defined memory as unsigned characters, including string literals, and then of course to cast a pointer that points to a string literal back to char *
.
In
uint8 *my_string = "XYZ";
"XYZ"
is an anonymous array of 4 char
s - including the terminating zero. This decays into a pointer to the first character. This is then implicitly converted to uint8 *
- strictly speaking, it should have an explicit cast though.
The problem with the type char
is that the standard leaves it up to the implementation to define whether it is signed or unsigned. If there is lots of arithmetic with the characters/bytes, it might be beneficial to have them unsigned by default.
A particularly notorious example is the <ctype.h>
with its is*
character class functions - isspace
, isalpha
and the like. They require the characters as unsigned char
s (converted to int)! A piece of code that does the equivalent of char c = something(); if (isspace(c)) { ... }
is not portable and a compiler cannot even warn about this! If the char
type is signed on the platform (default on x86!) and the character isn't ASCII (or, more properly, a member of the basic execution character set), then the behaviour is undefined - it would even abort on MSVC debug builds, but unfortunately just causes silent undefined behaviour (array access out of bounds) on glibc.
However, a compiler would be very loud about using unsigned char *
or its alias as an argument to strlen
, hence the cast.