有谁知道C规范的哪个部分描述了后面的行为:
以下代码片段重现了这种情况(请注意,有一些样板代码可以避免某些不会导致问题的编译优化):
volatile int zero = 0;
unsigned int someint = 20;
if(zero == 1)
{
someint += 1;
}
double x = -someint;
编译器( clang 3.5.0 ,但 gcc 4.9.1 发出类似的东西)为最后一次分配发出以下内容:
mov eax,DWORD PTR [rbp-0xc] <-- move someint in eax
neg eax
mov ecx,eax
cvtsi2sd xmm0,rcx
movsd QWORD PTR [rbp-0x18],xmm0
有趣的是,两个补码否定( neg )是在双字( eax )上执行的,但是dword是双精度转换(< em> cvtsi2sd )在qword( rcx )上执行,其低32位为负数-20(mov ecx,eax),其高32位全为0。 由于 eax 未签名扩展到 rcx , rcx 现在保留一个正数,最后在 x 中结束转换。
另一方面,如果 someint 被转换为赋值中的 int ,则双精度转换的双字( cvtsi2sd )是在dword( ecx )上执行,因此最终结果是 x 中预期的-20。
答案 0 :(得分:4)
没有“负无符号整数”这样的东西。无符号整数总是正数。如果someint = 0,则-someint产生值0,而UINT_MAX + 1 - 否则根据C规则产生。改为使用
double x = - (double) someint;
答案 1 :(得分:1)
为了创造一个消极的&#34;来自double
的{{1}}您必须首先否定为unsigned int
和integer
至cast
(通过按位否定或更改符号):
double
<强>输出:强>
#include <stdio.h>
int main () {
unsigned int x = 44231; /* unsigned number */
int i = ~x; /* bitwise not gives negative */
double d = (double)i; /* cast to double */
double e = (double)(int)~x; /* all in one set of casts */
printf ("\n unsigned x = %u\n", x);
printf (" int i = ~(x) = %d\n", i);
printf (" double d = (double)i = %lf\n\n", d);
printf (" double e = (double)(int)~(x) = %lf\n\n", e);
return 0;
}
答案 2 :(得分:0)
根据我的说法,你需要在将它分配给x之前对你的someint进行类型转换。