2017-04-10 403 views
2

这个很简单。Printf的奇怪输出无符号长整数

printf("%lu\n", (unsigned long)(320 * 200)); 

该行代码打印出“4294965760”。这绝对不等于360 * 200.它有什么问题?

我在16位中型内存模型中使用了Digital Mars C编译器。

+0

[无法重现您的结果](http://ideone.com/5DEcfs) – dasblinkenlight

+2

您将*结果*转换为'320 * 200',但这是64000和64000不符合带符号的16位整数未定义的行为)。不用'320 * 200'附近的圆括号再试一次。如果仍然失败:诅咒编译器。 – deamentiaemundi

+0

但是一个无符号长整数不是一个16位整数,它是无符号的。这是一个4字节的int,这意味着32位......所以诅咒编译器? – SeanRamey

回答

4

在16位系统中,如果sizeof(int) == 2,然后320 * 200,这等于64000,太大的签署int(范围±32,767 - 通常-32,768过,但在理论上它因平台而异)。所以,你有算术溢出。演员阵容不会影响乘法;它只影响乘法结果发生的情况。

你会做的更好:

printf("%lu\n", 320UL * 200UL); 

,迫使常量unsigned long

+0

我不明白?那不是我所拥有的?每个人从哪里得到“签名的Int”?我清楚地将320 * 200类型转换为4字节的unsigned long int,并使用“%lu”表示将unsigned long int打印出来。 – SeanRamey

+0

这工作!但为什么?我不明白吗?常数和类型转换有什么不同? – SeanRamey

+3

320是一个(带符号)'int'值。 200是一个(带符号)'int'值。当编译器看到“320 * 200”时,它必须乘以两个(带符号)“int”值,这会产生(符号和溢出)“int”值。然后,当它完成时,它必须将结果(溢出(带符号)的'int'值)转换为'unsigned long'。溢出的值是负值;这意味着一个很大的'无符号长'值。你可以使用'320U * 200U',因为'64000'小于'65535',最大16位'unsigned int',并将其转换为'unsigned long'也会干净。 –

-1

我刚刚在我的代码中试过这个,我得到64000. 也许问题是320*200是一个有符号数!当你投掷它时,他们在比特级有问题吗?尝试

unsigned long x = 320*200; 
printf("%lu\n", x); 
//64000 =      0b1111101000000000 
//4294965760 = 0b11111111111111111111101000000000 

看到第一位匹配!所以这可能是演员的问题。