Does the current bit pattern of a variable in memory distinguish between signed and unsigned int?

I want to pass a 32-bit signed integer x through a socket. To let the recipient know what byte order to expect, I call htonl(x) before sending. htonl expects a uint32_t , although I want to be sure of what happens when I overlay int32_t on uint32_t .

 int32_t x = something; uint32_t u = (uint32_t) x; 

Is it always the case that the bytes in x and u will be the same? How about dropping:

 uint32_t u = something; int32_t x = (int32_t) u; 

I understand that negative values ​​are passed into large unsigned values, but that doesn't matter, as I just go back to the other end. However, if cast riots with actual bytes, then I cannot be sure that dropping will return the same value.

+21
c casting int unsigned htonl
Oct 21 '13 at 9:06 on
source share
3 answers

In general, casting in C is specified in terms of values, not bit patterns - the former will be saved (if possible), but the latter is not necessarily the case. In the case of two views with padding without padding - which is mandatory for fixed integer types - this distinction does not matter, and the cast will indeed be noop.

But even if the conversion from signed to unsigned would change the bit pattern, converting it back again will restore the original value - with the warning that an unconfigured unsigned conversion to a signature is realistic and can raise an overflow signal.

For full portability (which is likely to be redundant), you will need to use the punning function instead of the conversion. This can be done in one of two ways:

Using pointer pointers i.e.

 uint32_t u = *(uint32_t*)&x; 

with which you should be careful, as this may violate effective input rules (but this is normal for options with signed / unsigned integer types) or through unions, i.e.

 uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u; 

which can also be used, for example, to convert from double to uint64_t , which you cannot follow with pointers if you want to avoid undefined behavior.

+19
Oct 21 '13 at 9:36 on
source share

C uses roles that mean both “type conversion” and “value type”. If you have something like

 (float) 3 

Then it's a type conversion, and the actual bits change. If you say

 (float) 3.0 

it is a value type.

Assuming a presentation with two additions (see comments below), when you click int on unsigned int bit diagram does not change, but only its semantic value; if you return it, the result will always be correct. This applies to the case of type ambiguity, since no bits are changed, only how the computer interprets them.

Note that theoretically 2 additions cannot be used, and unsigned and signed can have very different representations, in which case the actual bit diagram may change.

However, from C11 (the current C-standard), you are guaranteed that sizeof(int) == sizeof(unsigned int) :

(§6.2.5 / 6) For each of the signed integer types, there is a corresponding (but different) unsigned integer type (indicated by the unsigned keyword) that uses the same amount of storage (including the character) and has the same alignment requirements [ ...]

I would say that in practice, you can assume that it is safe.

+6
Oct 21 '13 at 9:18
source share

This should always be safe, since intXX_t types intXX_t guaranteed in two additions , if they exist:

7.20.1.1. Integers of exact width. The name typedef intN_t denotes an integer type with a sign with a width of N, no complement bits and two padding. Thus, int8_t denotes such an integer with a signed type with a width of exactly 8 bits.

Theoretically, the inverse transform from uint32_t to int32_t is determined by the implementation, as with all unsigned to signed conversions. But I can’t imagine that the platform will work differently than you expect.

If you want to be sure of this, you can still convert it manually. You just need to check the value for > INT32_MAX , and then do some math. Even if you do it systematically, a decent compiler should be able to detect this and optimize it.

+2
Oct 21 '13 at 10:04 on
source share



All Articles