开发者

C usual arithmetic conversions

开发者 https://www.devze.com 2023-04-08 10: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

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.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

So let's say I have the following code:

#include <stdio.开发者_运维知识库h>

int main()
{
    unsigned int a = 10;
    signed int b = -5;

    printf("%d\n", a + b); /* 5 */
    printf("%u\n", a + b); /* 5 */
    return 0;
}

I thought the bolded paragraph applies (since unsigned int and signed int have the same rank. Why isn't b converted to unsigned ? Or perhaps it is converted to unsigned but there is something I don't understand ?

Thank you for your time :-)


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)


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.


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


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

精彩评论

暂无评论...
验证码 换一张
取 消