18

Normally I imagine most people would use int for everything and ocassionally they would use unsigned int when needed. Every now and then you might use a short int, maybe for network traffic or something.

But lately I have started to use std::size_t for indexing into STL containers (as I should), and then I started to find a use for std::uint8_t when creating a struct of four 8-bit colour values (RGBA), rather than a char, simply because it makes more sense to me (it's a number, not a character type, and not a 8-bit value, it's a 8-bit number from 0-255).

Then while doing some network programming I found that I wanted to make sure certain values being passed were 16-bits. And according to https://en.cppreference.com/w/cpp/language/types I can't assume a short int is 16 bits, only that it's at least 16 bits. So I found a use for std::int16_t.

This led me to gradually start using a fixed-width type everywhere. Which caused me to really think about what I needed, how much range I needed etc, whether it would fall into negative values or not.

So now, I have almost zero occurences of int in my code.

There's three reasons in my head for this:

  1. It makes my intent clear to someone else (i.e., I don't expect the number to be larger than this or it won't be negative)
  2. Code is more portable. If I want a 16bit integer type, it will be 16 bit on every compiler
  3. Saves memory. Though I imagine on a modern PC this is largely unimportant.

But I'm concerned that this is reducing performance as your usual consumer-grade CPU would operate on a native width type like a std::int32_t better.

So, when should I use the fixed-width types, and how do they impact performance?

NeomerArcana
  • 1,978
  • 3
  • 23
  • 50
  • Your 3 assumptions are correct. – Piotr Siupa Jul 22 '19 at 08:01
  • @NO_NAME But isn't the fourth assumption (concern) also correct? – Benjamin Bihler Jul 22 '19 at 08:01
  • 1
    There should be no impact on performance. Fixed length types usually are just aliases to basic types. Compiler/library just looks which type (`short int`, `int`, `long int`) has 4 bytes and creates an alias named `int32_t`. – Piotr Siupa Jul 22 '19 at 08:03
  • Here is code for measuring some operations: https://stackoverflow.com/a/36994001/2492801. It seems as if it depends... – Benjamin Bihler Jul 22 '19 at 08:07
  • After I'd learned about fixed length types, I basically stopped using normal ones. O don't know why are they so loosely defined but it's probably some historical reason. Nowadays, I would recommend them only for simple programs which you write in half an hour and are to lazy to think about types. – Piotr Siupa Jul 22 '19 at 08:07
  • 2
    Shorter types *can* be faster, as it allows to fit more data into cache. – zett42 Jul 22 '19 at 08:09
  • related: https://stackoverflow.com/questions/31037764/are-the-fixed-width-integer-types-guaranteed-to-be-typedefs-for-the-standard-bui – Piotr Siupa Jul 22 '19 at 08:13

1 Answers1

4

You should use int when writing portable code (unless the integer size is constrained by external factors (e.g. protocol parsing), because this will allow machines to use the integer size that is preferred (optimal) on that machine.

There are a number of microprocessors in use whose register size is 16 bits for example; the compiler headers they provide set sizeof(int) to 2. Using e.g. int32_t on these machines for arithmetic would generate a lot of extra instructions.

However: For indexing, using int is a bad idea: size_t is preferable, even if you're guaranteed not to overflow the index by using int. This is because the value may need to be converted to the index register size (e.g. 64 bits for size_t vs 32 bits for int). This can be costly in inner loops.

Josh Greifer
  • 3,151
  • 24
  • 25
  • 4
    On the other hand, you can use `int_fastXX_t`. – Piotr Siupa Jul 22 '19 at 08:08
  • 1
    It's also worth noting that the standard only guarantee that `int` has 2 bytes, so if you write portable code with standard types, you need to take this into account. – Piotr Siupa Jul 22 '19 at 08:18
  • but the standard also doesn't seem to guarantee the fixed length values - 'optional : provided only if the implementation directly supports the type' [Fixed width integer types](https://en.cppreference.com/w/cpp/types/integer) – Thomas Jul 22 '19 at 08:22
  • 1
    If you're worried that implementation doesn't support your specific length of type, you can use `int_leastXX_t` and if you really need a specific size of variable and the implementation doesn't support it, you are screwed anyway, regardless if you use `stdint` or base types. – Piotr Siupa Jul 22 '19 at 08:28
  • I believe the `int_fastXX_t` and `int_leastXX_t` are not optional but required by the standard. – NeomerArcana Jul 22 '19 at 08:29
  • 1
    The answer is a little bit short for my taste - what exactly can happen wrong? How might an Int16 cause things to be slower? Is there some kind of source on that? Let me make this clear, I am not saying that you are wrong, just that the those things should be a part of the answer. – Aziuth Jul 22 '19 at 09:02
  • @Aziuth - I agree, I was intending to give examples based on my expereinces with embedded programming for PIC, started to look at the Arduino to confirm that sizeof(int) == 2, then got distracted! Will update my answer – Josh Greifer Jul 22 '19 at 09:57
  • There are different perspectives. I would say, you should never ever nowhere use int. Especially not for portable code. Do not use it. In serious software (saftey critical) nobody would use int. In autmotive you have also MISRA rules available that say. Do not use int. Always use typedefs (or using). Do not use build in standard integer, float char or bool types. Wow. – A M Jul 22 '19 at 10:42
  • @ArminMontigny That sounds quite hard, could you elaborate? In any case, I work with Qt, which pretty much forces me to use int, as Qt widgets use int for indices and more. Would those rules not allow one to use such libraries? Also, what is wrong with bool? – Aziuth Jul 22 '19 at 10:56
  • @ArminMontigny Agree in this case: A similar set of rules exist for medical device software/firmware. But in cases like these, the safety issue is paramount, rather than performance. – Josh Greifer Jul 22 '19 at 11:02
  • 30 years ago, when I relied on the size of a union containing an int (16 bit) and some other prohect and was then resusing the code in Turbo C, I produced a hard bug. Int was suddenly 32 bits (24 bits on Microchip PIC). That was the last time when I used int in productive code. And then we switched to Watcom C++ and we used the PharLap DosExtender. With that we could suddenly access more than 1 MByte. (1 Megabyte, not Gigabyte). 32 bit integers wow. Nowadys we are running LINT, QAC, Coverity, Polyspace and SONAR Cube. Usage of int datatype will produce an error. The Build will not run . . . – A M Jul 22 '19 at 14:30
  • @JoshGreifer wouldn't using the `int_fastXX_t` be a better alternative than `int`? Because these would have to be the same as the register size for any type less than or equal to the register size. – NeomerArcana Jul 22 '19 at 22:48
  • The issue with speed mainly comes with the larger integer types. If the processor is of limited bit width (say 16 bits), the compiler is still capable of generating code that works for bigger types, (say int32_t), but that code will take multiple processor operations. an add of 2 32-bit ints requires 2 16-bit adds using processor carry. A multiply of 2 32-bit values requires 3 16-bit multiplies (the 4th is guaranteed to overflow). – Gem Taylor Jul 23 '19 at 14:44
  • Potentially a processor might not support small integer sizes natively. Operations would appear to use the smaller type but would actually use the native type, It could still read those values from memory by reading larger values and then shifting and masking them. To write a value, it would need to read the larger native type value, shift and mask the result value into it, then write the larger native type value. A compiler writer might choose to support that type and provide these complex operations, or choose not to define the type. – Gem Taylor Jul 23 '19 at 14:50
  • @GemTaylor I understand this. But considering that `int_fastXX_t` are required by the standard, and are *at least* the size but could be more; wouldn't they be a better and more intentional type to use than just `int`? – NeomerArcana Jul 25 '19 at 02:40
  • @NeomerArcana yes you can. Of course, if you want to minimise memory usage you wouldn't, if you were willing to accept some potential access penalty. The OP asked what the downsides were of using the fixed types, and I didn't feel that anyone had actually described those downsides. – Gem Taylor Jul 25 '19 at 10:03