将负的unsigned int分配给C中的double

时间:2014-12-23 00:21:13

标签: c double standards variable-assignment unsigned-integer

有谁知道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。

3 个答案:

答案 0 :(得分:4)

没有“负无符号整数”这样的东西。无符号整数总是正数。如果someint = 0,则-someint产生值0,而UINT_MAX + 1 - 否则根据C规则产生。改为使用

double x = - (double) someint;

答案 1 :(得分:1)

为了创造一个消极的&#34;来自double的{​​{1}}您必须首先否定为unsigned intintegercast(通过按位否定或更改符号):

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进行类型转换。