我有一个简单的程序,其中我有几个宏位操作。
其中一个宏转换为
unsigned long val = 1 << 0x1f;
在这里,我得到的输出是
val = 0xffffffff80000000;
我知道这是某种int溢出。我对最终结果的那一部分感到困惑。为什么结果会成为我所得到的结果呢?
(我在这里理解,因为某种原因,1被视为int,当左移位使其为负int时。但我对这种类型的铸造感到困惑。)
发布于 2015-10-01 22:55:21
1
是一个有符号整数,因此在溢出的情况下,它是未定义的行为。
根据标准(强调地雷):
E1 << E2
的结果是E1
左移的E2
位位置;空出的位充满了零。如果E1
具有无符号类型,则结果的值为E1 × 2E2
,减少的模值比结果类型中可表示的最大值多一个。如果E1 × 2E2
具有有符号类型和非负值,并且E1 × 2E2
在结果类型中是可表示的,那么这就是结果值;否则,行为是未定义的。
相反,尝试unsigned long
值1ul
unsigned long val = 1ul << 0x1f
(我在这里理解,因为某种原因,1被视为
int
,而当左移位使它成为负整数时)。但我对这种类型的铸造感到困惑。)
实际上,如果将符号位设置为1 (但是,按照标准,它是UB),实际上可能会发生这种情况。
尽管如此,让我们考虑一个法律案例(我使用了short
和int
,因为int
和long
在我的系统上具有相同的大小):
// on my system
short int s = SHRT_MIN; // 0x8000
unsigned int i = s; // 0xffff8000
标准的以下部分对此作了澄清:
6.3.1.3有符号整数和无符号整数 当具有整数类型的值转换为
_Bool
以外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变。 否则,如果新类型是无符号的,则通过重复增减一个比在新类型中表示的最大值更多的值来转换值,直到该值位于新类型的范围内为止。
(如果我正确地解释它),因为我们不能用无符号类型表示负值,所以我们将UINT_MAX + 1
添加到SHRT_MIN
中(用纯数学的术语,而不考虑溢出):
UINT_MAX + 1 + SHRT_MIN // 0xffff8000
https://stackoverflow.com/questions/32898056
复制相似问题