C usual arithmetic conversions

前端 未结 4 913
攒了一身酷
攒了一身酷 2020-12-01 15:08

I was reading in the C99 standard about the usual arithmetic conversions.

If both operands have the same type, then no further conversion is needed.

相关标签:
4条回答
  • 2020-12-01 15:45

    It is converted to unsigned, the unsigned arithmetic just happens to give the result you see. The result of unsigned arithmetic is equivalent to doing signed arithmetic with two's complement and no out of range exception.

    0 讨论(0)
  • 2020-12-01 15:48

    0x0000000a plus 0xfffffffb will always be 0x00000005 regardless of whether you are dealing with signed or unsigned types, as long as only 32 bits are used.

    0 讨论(0)
  • 2020-12-01 15:56

    Repeating the relevant portion of the code from the question:

    unsigned int a = 10;
    signed int b = -5;
    
    printf("%d\n", a + b); /* 5 */
    printf("%u\n", a + b); /* 5 */
    

    In a + b, b is converted to unsigned int, (yielding UINT_MAX + 1 - 5 by the rule for unsigned-to-signed conversion). The result of adding 10 to this value is 5, by the rules of unsigned arithmetic, and its type is unsigned int. In most cases, the type of a C expression is independent of the context in which it appears. (Note that none of this depends on the representation; conversion and arithmetic are defined purely in terms of numeric values.)

    For the second printf call, the result is straightforward: "%u" expects an argument of type unsigned int, and you've given it one. It prints "5\n".

    The first printf is a little more complicated. "%d" expects an argument of type int, but you're giving it an argument of type unsigned int. In most cases, a type mismatch like this results in undefined behavior, but there's a special-case rule that corresponding signed and unsigned types are interchangeable as function arguments -- as long as the value is representable in both types (as it is here). So the first printf also prints "5\n".

    Again, all this behavior is defined in terms of values, not representations (except for the requirement that a given value has the same representation in corresponding signed and unsigned types). You'd get the same result on a system where signed int and unsigned int are both 37 bits, signed int has 7 padding bits, unsigned int has 11 padding bits, and signed int uses a 1s'-complement or sign-and-magnitude representation. (No such system exists in real life, as far as I know.)

    0 讨论(0)
  • 2020-12-01 16:02

    Indeed b is converted to unsigned. However what you observed is that b converted to unsigned and then added to 10 gives as value 5.

    On x86 32bit this is what happens

    1. b, coverted to unsigned, becomes 4294967291 (i.e. 2**32 - 5)
    2. adding 10 becomes 5 because of wrap-around at 2**32 (2**32 - 5 + 10 = 2**32 + 5 = 5)
    0 讨论(0)
提交回复
热议问题