首页 > 代码库 > 整形提升(C语言基础)续

整形提升(C语言基础)续

Conversion rules are more complicated when unsigned operands are involved. The problem is that comparisons between signed and unsigned values are machine-dependent, because they depend on the sizes of the various integer types. For example, suppose that int is 16 bits and long is 32 bits. Then -1L < 1U, because 1U, which is an unsigned int, is promoted to a signed long. But -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number.

I tried the code below in two different scenarios:

  1. compiled on an x86 64bits platform and executed. Where sizeof(-1L) -> 8byte and sizeof(1U) -> 4 bytes
  2. compiled on an x86 32bits platform and executed. Where sizeof(-1L) -> 4byte and sizeof(1U) -> 4 bytes

The code:

int main() { if(-1L > 1U)    printf("true");    else    printf("false");    return 0;}

The results:

  1. x86 64bits: false
  2. x86 32bits: true

 

lets explain the rank system first

6.3.1 Arithmetic operand(c99 standard)A) The rank of a signed integer type shall be greater than the rank of any signed integertype with less precision(more bytes higher precision higher rank)B) The rank of long long int shall be greater than the rank of long int, which shall begreater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.C) The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.(in other words if your system unsigned int is 32bits and your int is 32bits then the ranks of these are the same.)

the above explains the rank.

now coming to arithmetic conversions.

6.3.1.8 Usual arithmetic conversions (c99 standard)1)If both operands have the same type, then no further conversion is needed.2)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.(similar to 1)3)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.4)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 type5)Otherwise, both operands are converted to the unsigned integer type corresponding to the  type of the operand with signed integer type.

2) compiled on an x86 32bits platform and executed. Where sizeof(-1L) -> 4byte and sizeof(1U) -> 4 bytes

in your case look at statement 3 & C. the unsigned value(4bytes) has rank equal to the signed value(4btyes) therefore the singed value is converted to an unsigned value, when this happens the, the sign bit makes this look like a extremely large value. -1L > 1U therefore is true

1) compiled on an x86 64bits platform and executed. Where sizeof(-1L) -> 8byte and sizeof(1U) -> 4 bytes

in this case, the unsigned value rank is less than the rank of the singed value. look at 4). the signed integer(8bytes) can represent any 4byte unsigned value. therefore the unsigned 4byte value is converted to a signed value.(this will preserve the sign bit, sign bit is 0)

therefore -1L > 1U is false