无符号和更大的符号类型之间的隐式转换不一致的行为 [英] Inconsistent behaviour of implicit conversion between unsigned and bigger signed types
问题描述
考虑下面的例子:
的#include<&stdio.h中GT;INT主要(无效)
{
unsigned char型一= 15; / *一个字节* /
无符号短B = 15; / *两个字节* /
unsigned int类型C = 15; / *四个字节* / 长×= -a; / *八个字节* /
的printf(%LD \\ N,X); X = -b;
的printf(%LD \\ N,X); X = -c;
的printf(%LD \\ N,X); 返回0;
}
要编译我使用GCC 4.4.7(和它没有给我警告):
gcc的-g -std = C99 -pedantic-错误-Wall -W check.c
我的结果是:
-15
-15
4294967281
问题是,为什么这两个 unsigned char型
和无符号短
值是传播正确地(签字)长
,而 unsigned int类型
是不是?是否有任何引用或规则上呢?
下面是从 GDB
的结果(词在little-endian顺序)相应的:
(GDB)x / 2W和放大器; X
0x7fffffffe168:11111111111111111111111111110001 11111111111111111111111111111111(GDB)x / 2W和放大器; X
0x7fffffffe168:11111111111111111111111111110001 00000000000000000000000000000000
这是由于如何应用到操作数和一元减法的结果有相同的类型要求的整数促销。这是覆盖在部分 6.5.3.3
的单目算术运算符的和说(的重点煤矿前进的):
一元的结果 - 运算符是它的(推动)操作数的负值。 整数促销活动上进行操作,结果具有推广型
块引用>和它覆盖在C99标准草案部分整型提升
6.3
的转换的说:
如果int可以重新present原始类型的所有值,该值被转换为int;否则,将其转换为一个unsigned int。这些被称为整数促销。 48)所有其它类型在整数提升不会改变。
块引用>在在前两种情况下,推广将是的 INT 的,其结果将是的 INT 的。在的情况下的 的要求unsigned int类型没有任何推广,但结果将需要转换回的 unsigned int类型的
的
-15
被转换成的 unsigned int类型的使用列明有关规则6.3.1.3
的符号和无符号整数的它说:
否则,如果新类型是无符号的值被重复地增加或减1比可以重新$ P $在新型psented直到该值是在新的类型的范围的最大值更转换 49)
块引用>因此,我们最终与
-15 +(UMAX + 1)
这将导致UMAX - 14
这将导致在一个大的无符号值。这就是为什么有时候你会看到code使用1
转换为一个无符号的值,以获得一个类型,因为它总是会最终成为的最大无符号值-1 + UMAX + 1
是UMAX
。Consider following example:
#include <stdio.h> int main(void) { unsigned char a = 15; /* one byte */ unsigned short b = 15; /* two bytes */ unsigned int c = 15; /* four bytes */ long x = -a; /* eight bytes */ printf("%ld\n", x); x = -b; printf("%ld\n", x); x = -c; printf("%ld\n", x); return 0; }
To compile I am using GCC 4.4.7 (and it gave me no warnings):
gcc -g -std=c99 -pedantic-errors -Wall -W check.c
My result is:
-15 -15 4294967281
The question is why both
unsigned char
andunsigned short
values are "propagated" correctly to (signed)long
, whileunsigned int
is not ? Is there any reference or rule on this ?Here are results from
gdb
(words are in little-endian order) accordingly:(gdb) x/2w &x 0x7fffffffe168: 11111111111111111111111111110001 11111111111111111111111111111111 (gdb) x/2w &x 0x7fffffffe168: 11111111111111111111111111110001 00000000000000000000000000000000
解决方案This is due to how the integer promotions applied to the operand and the requirement that the result of unary minus have the same type. This is covered in section
6.5.3.3
Unary arithmetic operators and says (emphasis mine going forward):The result of the unary - operator is the negative of its (promoted) operand. The integer promotions are performed on the operand, and the result has the promoted type.
and integer promotion which is covered in the draft c99 standard section
6.3
Conversions and says:if an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.48) All other types are unchanged by the integer promotions.
In the first two cases, the promotion will be to int and the result will be int. In the case of unsigned int no promotion is required but the result will require a conversion back to unsigned int.
The
-15
is converted to unsigned int using the rules set out in section6.3.1.3
Signed and unsigned integers which says:Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49)
So we end up with
-15 + (UMAX + 1)
which results inUMAX - 14
which results in a large unsigned value. This is sometimes why you will see code use-1
converted to to an unsigned value to obtain the max unsigned value of a type since it will always end up being-1 + UMAX + 1
which isUMAX
.这篇关于无符号和更大的符号类型之间的隐式转换不一致的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!