Convert uint32_t to int32_t without risk of overflow or excessive complexity

How do I better convert uint32_t to int32_t fast with wrapping in C ++?

Some attempts:

 uint32_t y = UINT32_MAX; int32_t x = (int32_t)y; // UB on overflow int32_t x = *(int32_t*)&y; // does this violate strict aliasing? 
+8
c ++ undefined-behavior
source share
3 answers

int32_t x = (int32_t)y; not overflowing, not UB. Overflow is when an arithmetic operation returns a result outside the range of the represented values. However, the conversion is not an arithmetic operation.

This situation is determined by behavior. All implementations that I know define behavior as not changing the view.

Please note that no cast is required here. You can write int32_t x = y; . In practice, this is simpler and will always work. So much code relies on this that no vendor is ever going to define any other behavior (and not that they have every reason for this anyway).


int32_t x = *(int32_t*)&y not UB. It does not violate a strict alias because a signed version of a type is allowed for aliases of an unsigned version. This code is guaranteed to create int32_t with the same representation as the corresponding uint32_t (ie, "Wrap", as these types are guaranteed to be 2 additions).

+5
source share
 union { int32_t i; uint32_t u; } u; ui = ...; printf("%" PRIu32 "\n", uu); 

This and memcpy(&uint_var, &int_var, sizeof uint_var) are two standard ways to do this conversion without invoking undefined behavior.

See also:

  • Is type-punning through union unspecified in C99 and has it been specified in C11?
+5
source share
 #include <assert.h> #include <limits.h> #include <stdlib.h> int makesigned(unsigned x) { if (x <= (unsigned) INT_MAX) { return (int) x; } /* assume 2 complement */ if (x >= (unsigned) INT_MIN) { return 0 - (int)(-x); } abort(); return 0; } int main(void) { assert(makesigned(0) == 0); assert(makesigned(INT_MAX) == INT_MAX); assert(makesigned(UINT_MAX) == -1); assert(makesigned(INT_MIN) == INT_MIN); return 0; } 
+1
source share

All Articles