cstdint

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


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.


Solution

  • 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.


    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.


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


    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))