int8_t vs char ; Which is the best one?
Solution 1
The use of int8_t
is perfectly good for some circumstances - specifically when the type is used for calculations where a signed 8-bit value is required. Calculations involving strictly sized data [e.g. defined by external requirements to be exactly 8 bit in the result] (I used pixel colour levels in a comment above, but that really would be uint8_t
, as negative pixel colours usually don't exist - except perhaps in YUV type colourspace).
The type int8_t
should NOT be used as a replacement of char
in for strings. This can lead to compiler errors (or warnings, but we don't really want to have to deal with warnings from the compiler either). For example:
int8_t *x = "Hello, World!\n";
printf(x);
may well compile fine on compiler A, but give errors or warnings for mixing signed and unsigned char values on compiler B. Or if int8_t
isn't even using a char
type. That's just like expecting
int *ptr = "Foo";
to compile in a modern compiler...
In other words, int8_t
SHOULD be used instead of char
if you are using 8-bit data for caclulation. It is incorrect to wholesale replace all char
with int8_t
, as they are far from guaranteed to be the same.
If there is a need to use char
for string/text/etc, and for some reason char
is too vague (it can be signed or unsigned, etc), then usign typedef char mychar;
or something like that should be used. (It's probably possible to find a better name than mychar
!)
Edit: I should point out that whether you agree with this or not, I think it would be rather foolish to simply walk up to whoever is in charge of this "principle" at the company, point at a post on SO and say "I think you're wrong". Try to understand what the motivation is. There may be more to it than meets the eye.
Solution 2
They simply make different guarantees:
char
is guaranteed to exist, to be at least 8 bits wide, and to be able to represent either all integers between -127 and 127 inclusive (if signed) or between 0 and 255 (if unsigned).
int8_t
is not guaranteed to exist (and yes, there are platforms on which it doesn’t), but if it exists it is guaranteed to an 8-bit twos-complement signed integer type with no padding bits; thus it is capable of representing all integers between -128 and 127, and nothing else.
When should you use which? When the guarantees made by the type line up with your requirements. It is worth noting, however, that large portions of the standard library require char *
arguments, so avoiding char
entirely seems short-sighted unless there’s a deliberate decision being made to avoid usage of those library functions.
Solution 3
int8_t
is only appropriate for code that requires a signed integer type that is exactly 8 bits wide and should not compile if there is no such type. Such requirements are far more rare than the number of questions about int8_t
and it's brethren indicates. Most requirements for sizes are that the type have at least a particular number of bits. signed char
works just fine if you need at least 8 bits; int_least8_t
also works.
Solution 4
int8_t
is specified by the C99 standard to be exactly eight bits wide, and fits in with the other C99 guaranteed-width types. You should use it in new code where you want an exactly 8-bit signed integer. (Take a look at int_least8_t
and int_fast8_t
too, though.)
char
is still preferred as the element type for single-byte character strings, just as wchar_t
should be preferred as the element type for wide character strings.
sokid
Updated on June 03, 2021Comments
-
sokid almost 3 years
I know both are different types (
signed char
andchar
), however my company coding guidelines specifies to useint8_t
instead ofchar
.So, I want to know, why I have to use
int8_t
instead ofchar
type. Is there any best practices to useint8_t
? -
Kerrek SB almost 11 yearsWho guarantees two's complement? Reference please?
-
Stephen Canon almost 11 years7.20.1.1 Exact-width integer types, paragraph 1: “The typedef name intN_t designates a signed integer type with width N, no padding bits, and a two’s complement representation.” (Emphasis mine).
-
Grijesh Chauhan almost 11 yearsIs it possible in an language/platform one byte != 8 bits ?
-
Stephen Canon almost 11 years@GrijeshChauhan: Yes, in C a “byte” is defined to be “the size of a
char
”, and achar
is defined to be the smallest addressable unit of memory. There exist architectures (mostly DSPs) on which the smallest addressable unit of memory is 16, 24, or even 32 bits. -
sokid almost 11 yearsstdint.h has typedefs for all fundamental types, why it is not defined for 'char'?
-
Mats Petersson almost 11 yearsThis type probably doesn't exist in a platform where a byte is not 8 bits. Hence it is "not guaranteed to exist" - but if it does, it works in the way described, rather than in the less strictly defined way that
char
orint
orlong
works in C and C++. -
Grijesh Chauhan almost 11 years@MatsPetersson Just found a link, I like to share with you: System where 1 byte != 8 bit?
-
Kerrek SB almost 11 yearsThanks for the reference!
-
sokid almost 11 yearsSo, you mean, my company guidelines is short-sighted? :-( But in some cases you cant guaranty as char is always 8bits, so that may a reason to avoid the confusion they don't want to use char type
-
sokid almost 11 yearsstdint.h has typedefs for all fundamental types, why it is not defined for 'char'?
-
Mats Petersson almost 11 yearsIf your company is telling you to use
int8_t
for something that is in fact achar
value for example in a string, yes. If you are usingint8_t
because you want a small integer, to perform calculations (e.g. pixel colour values), thenint8_t
is very much the right thing to do. Note that although it may well compile fine to useint8_t *x = "Hello, World!\n"; printf(x);
on your platform, it may not work on another. -
Mats Petersson almost 11 yearsAnd
<stdint.h>
does not define ALL types. It defines standard types that aren't part of the compiler itself (such aschar
,int
,long
,float
, etc). -
Stephen Canon almost 11 years@MatsPetersson: Please do, I’ve already written all I care to on the subject. It’s still too early here.
-
James Kanze almost 11 years@GrijeshChauhan There is at least one relatively modern platform where bytes are 9 bits (and
signed char
is 1's complement); it has a C++ compiler. And I've heard that on some embedded platforms, bytes are 16 or 32 bits. -
Grijesh Chauhan almost 11 years@JamesKanze Thanks! When I first read about it I was supper surprised! but its true. :)
-
James Kanze almost 11 yearsI'll take issue with your second sentence. First, all calculations will take place in
int
or larger, because of integral promotion. So you doubtlessly mean when you have to store small signed values in the least space possible. And for this,signed char
is probably preferable. About the only time you should seeint8_t
in code is when the type has to match some external protocol or hardware. (And pixels should probably beuint24_t
, with 8 bits per color, but that doesn't usually exist.) -
James Kanze almost 11 yearsAnd later: if
char
is 16 bits, thenint8_t
will not exist. It must be an addressable type (not a bit field), andchar
is required to be the smallest addressable type (supported in that C/C++ implementation, of course: some machines, such as VAX, supported addressing individual bits). -
sokid almost 11 yearsVery nice description for my question, thank you Mats Peterson.
-
Mats Petersson almost 11 years@JamesKanze Ok, I have amended for your comments. I do think that the essense of my message was quite clear tho':
char
is not a replacement forint8_t
and vice versa - they should not be used interchangeably. -
sokid almost 11 yearsThanks for your answer, I understood, and my preferred name for "mychar" is "ascii_t", is it a good name?
-
Mats Petersson almost 11 years
ascii_t
may be a better choice - although on an old IBM Mainframe, it would probably be accurate withebcdic_t
instead - are you going to have an#ifdef
around every one of them? ;) -
Stephen Canon almost 11 yearsTo be horribly pedantic, names ending in
_t
are reserved by POSIX, and shouldn’t be used for user-defined types. I can count the people who adhere to this guideline on one hand, however. -
Luciano almost 9 yearsI'd like to add that a "naked" char IS NOT guaranteed to be signed. The standard allows compilers to compile it as either signed or unsigned. IF you want an 8 bit signed integer value, you MUST use int8_t. char should be used if you want an ASCII character.