Assuming you’re using a compiler that supports C99 (or even just stdint.h), is there any reason not to use fixed-width integer types such as uint8_t?
One reason that I’m aware of is that it makes much more sense to use chars when dealing with characters instead of using (u)int8_ts, as mentioned in this question.
But if you are planning on storing a number, when would you want to use a type that you don’t know how big it is? I.e. In what situation would you want to store a number in an unsigned short without knowing if it is 8, 16, or even 32 bits, instead of using a uint16t?
Following on from this, is it considered better practice to use fixed-width integers, or to use the normal integer types and just never assume anything and use sizeof wherever you need to know how many bytes they are using?
It’s actually quite common to store a number without needing to know the exact size of the type. There are plenty of quantities in my programs that I can reasonably assume won’t exceed 2 billion, or enforce that they don’t. But that doesn’t mean I need an exact 32 bit type to store them, any type that can count to at least 2 billion is fine by me.
If you’re trying to write very portable code, you must bear in mind that the fixed-width types are all optional.
On a C99 implementation where
CHAR_BITis greater than8there is noint8_t. The standard forbids it to exist because it would have to have padding bits, andintN_ttypes are defined to have no padding bits (7.18.1.1/1).uint8_ttherefore also forbidden because (thanks, ouah) an implementation is not permitted to defineuint8_twithoutint8_t.So, in very portable code, if you need a signed type capable of holding values up to 127 then you should use one of
signed char,int,int_least8_torint_fast8_taccording to whether you want to ask the compiler to make it:signed charorint)int)int_least8_torsigned char)int_fast8_torint)The same goes for an unsigned type up to 255, with
unsigned char,unsigned int,uint_least8_tanduint_fast8_t.If you need modulo-256 arithmetic in very portable code, then you can either take the modulus yourself, mask bits, or play games with bitfields.
In practice, most people never need to write code that portable. At the moment
CHAR_BIT > 8only comes up on special-purpose hardware, and your general-purpose code won’t get used on it. Of course that could change in future, but if it does I suspect that there is so much code that makes assumptions about Posix and/or Windows (both of which guaranteeCHAR_BIT == 8), that dealing with your code’s non-portability will be one small part of a big effort to port code to that new platform. Any such implementation is probably going to have to worry about how to connect to the internet (which deals in octets), long before it worries how to get your code up and running 🙂If you’re assuming that
CHAR_BIT == 8anyway then I don’t think there’s any particular reason to avoid(u)int8_tother than if you want the code to work in C89. Even in C89 it’s not that difficult to find or write a version ofstdint.hfor a particular implementation. But if you can easily write your code to only require that the type can hold255, rather than requiring that it can’t hold256, then you might as well avoid the dependency onCHAR_BIT == 8.