# Whats the most effective int on a 8-Bit Microcontroller? [closed]

The size of an int is defined by the compiler, not by the processor. Thats why e.g. int_8 exist. However, I was thought that usually int is the most effective datatype. Is this still true when e.g. working on a Atmega8?

Atmega8 uses 16bit as many smaller system do. But using a 8bit int would save me one fetch and execution wouldn't it?

• int is not defined to be the most effective integer width, at all. There's nothing that even suggests that, but the C standard defines int must take at least the range 2⁻¹⁵ to 2¹⁵-1! what does "effective" even mean? nice, if you can use an 8bit integer to represent the values you need, by all means, do, but really: what do you do once it can't? How do you measure effectiveness when it comes to having to do some awkward multi-int8_t arithmetics to emulate a 16bit word? So, this question as it is is slightly underdefined. Can you explain what use case you're considering? – Marcus Müller Nov 10 '18 at 10:42
• No, the compiler does not "handle int best". Who says that? That's wrong. – Marcus Müller Nov 10 '18 at 10:56
• what? that makes no sense. Your assumption makes no sense. No, int is not the "best-handleable numeric data type". That's simply not the case. Stop presuming it is. – Marcus Müller Nov 10 '18 at 10:57
• You forget that the math done on 16 bit variables is different than what is done with 8 bit variables. So, yes, there's a lot to optimize if you have a smaller bit width. Really, you're a programmer, not a compiler: use the data type that fits your data, nothing more, nothing less. It's easy as that. – Marcus Müller Nov 10 '18 at 11:08
• @MarcusMüller A historical note: Kernighan&Ritchie (1978) in chapter 2.2 suggest int "typically reflecting the natural size of integers on the host machine". They then go on to refine int to short, long, unsigned . Very old stuff, of interest if you're using an ancient compiler. – glen_geek Nov 10 '18 at 16:36

The C and C++ standards (You didn't state which you use) have a number of requirements on the ranges that char, short, int, long and long long (in signed and unsigned variant) can represent. But these requirements leave a lot of options open, the exact mapping from those standard types to hardware types is compiler-dependent (and sometimes also on versions, command-line flags, etc.)

When programming for small embedded systems the use of these 'raw' types is not recommended because the relation to the size is complex. Better specify what you need and let the compiler/library decide how to handle that best.

When you need a specific size (for instance to match the memory layout of a message or a set of hardware registers, or - for unsigned only - you need modulo arithmetic) use the fixed size types: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t. It is possible that one of these types doesn't exist and you get a compiler error, but as you need the exact type that is for the best.

When you need a variable for calculation choose the smalles type that can handle your range, but allow the compiler to choose a larger type: int_fast8_t, uint_fast8_t, etc. This gives the best of both worlds: on an AVR, int_fast8_t will be a byte, but on a Cortex (where handling 8-bit arithmetic would be slower and use more instructions) it would be 32 bits. On your desktop it might be 64 bit, if the CPU can handle that faster.

When you want tos tore integer values, and you want to use as little space as possible, use one of the int_leastN_t/uint_leastN_t types. The compiler will choose the smallest type that can store at least the bist you specified.

And PS: use char only for ASCII. Even when you use the raw types (you shouldn't, but even then), don't use char as a small integer, because you never know whether it is signed or unsigned. And vice versa, don't use one of those *_t types if you want to store an ACII value, that is what char is for.

So IMO all built-in ints should be deprecated, except for char (which shouln't have been an int in the first place).

• Nice! Note that int*_fast_t and the like are C99; not quite sure they exist in C++ at all. – Marcus Müller Nov 10 '18 at 11:58
• @MarcusMüller -- they're in C++. They come in through <cstdint>. – Pete Becker Nov 10 '18 at 12:01
• One thing that's often overlooked: int8_t, etc. require a particular register size; if the hardware doesn't support that size, the type won't be defined. So for general use, int_least8_t or int_fast8_t, etc., are preferred. It's only if you really have to have exactly that number of bits that you use int8_t. Of course, for embedded systems that's usually the case: you're matching a particular register size, so it's often appropriate to use the exact type. – Pete Becker Nov 10 '18 at 12:07
• @ChrisStratton -- from the C99 standard, 7.20.1.1/3, Exact-width integer types: "These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits ... it shall define the corresponding typedef names." The preceding two paragraphs define the signed and unsigned types "with width N and no padding bits" (emphasis added). You may well be right that some compilers emulate these things with carefully designed (and inefficient) operations that imitate those exact sizes; nevertheless, they're not something you can rely on having. – Pete Becker Nov 10 '18 at 15:13
• But the end rule is still the same: if you need a specific size (for layout or for modulo arithmetic), use the fixed-size type.(If your compiler doesn't provide it, you're screwed anayway. OK, you could emulate it yoursef...) If not, use one of the fast types. – Wouter van Ooijen Nov 10 '18 at 15:23