In general, casting in C is specified in terms of values, not bit patterns - the former will be preserved (if possible), but the latter not necessarily so. In case of two's complement representations without padding - which is mandatory for the fixed-with integer types - this distinction does not matter and the cast will indeed be a noop.
But even if the conversion from signed to unsigned would have changed the bit pattern, converting it back again would have restored the original value - with the caveat that out-of-range unsigned to signed conversion is implementation-defined and may raise a signal on overflow.
For full portability (which will probably be overkill), you'll need to use type punning instead of conversion. This can be done in one of two ways:
Via pointer casts, ie
uint32_t u = *(uint32_t*)&x;
which you should be careful with as it may violate effective typing rules (but is fine for signed/unsigned variants of integer types) or via unions, ie
uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u;
which can also be used to eg convert from double
to uint64_t
, which you may not do with pointer casts if you want to avoid undefined behaviour.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…