Home > OS >  How does casting between Cs default int type and <stdint.h>'s intXX_t types work?
How does casting between Cs default int type and <stdint.h>'s intXX_t types work?

Time:10-23

I'm working in a code skeleton that has a lot of preexisting code using the regular old int type in C. However, the code I need to write requires that I use a fixed length int32_t. However, I need to be able to take input from the regular code in terms of int, and output to variables that are also just regular int. Does casting from int32_t to int preserve the value of the variable, or the specific data representation of it (in which case I may need to bitshift in order to preserve the value). Conversely, does casting from int to int32_t introduce any complications? Any answer would be greatly appreciated, but especially any that generally and specifically explain the casting conventions of the stdint library.

CodePudding user response:

How does casting between Cs default int type and <stdint.h>'s intXX_t types work?

When intXX_t and int same size, range and effective type, no "work" really happens.

When intXX_t has wider range than int, all values are preserved in the new type. The upper bits are a sign extension.

When intXX_t has narrower range than int, out of range values are converted in an implementation defined way. This is very commonly a mod like wrap around (lower bits are the same)

When intXX_t has same range as int, the types may differ, but usually are the same. In select code (as with _Generic), the difference is important.


int comes in various sizes and encoding.

  • 32-bit (2's complement): This is quite common, especially on desktop computers.

  • 16-bit (2's complement): This is common in small embedded processors.

  • Other: including Non-2's complement, 64-bit on some 64-bit graphics processors, some non-power-of-2 on old or esoteric machines. For OP's concerns, simply know others exists, but it is very unlikely OP needs to port code to or from such machines.


Does casting from int32_t to int preserve the value of the variable, or the specific data representation of it (in which case I may need to bitshift in order to preserve the value).

Bit shifting not needed.

  • 32-bit (2's complement): Casting int32_t to int does not lose any value information. In select situations, a type change may happen. int32_t may have been type def'd as a long, yet far more likely int32_t, int are exactly the same type.

  • 16-bit (2's complement): Casting int32_t to int loses info as the the range is much smaller. On such machines, better to cast int32_t to long.


Conversely, does casting from int to int32_t introduce any complications?

  • 32-bit (2's complement): Very unlikely any problem.

  • 16-bit (2's complement): Some situations deserve review as int32_t is wider and takes up more space.


Well written code is less likely to cause issues, yet much code does not consider portability.

For OP's case, I recommend to create macros, rather than direct casting. This will facilitate tracking the change to your code base due to the new work requirement. Further, alternatives could then readily be used to debug range reduction/increase issues.

// Use names per your coding style
#define inttoint32(i) ((int32_t) (i))
#define int32toint(i32) ((int) (i32))
  • Related