我正在研究K&R第二版,并且无法弄清楚为什么我会得到一定的结果.我正在解决的问题是计算数据类型的上限和下限.特别:
"编写一个程序来确定char,short,int和long变量的范围,包括有符号和无符号,通过从标准头文件中打印适当的值并直接计算.如果你计算它们会更难:确定各种浮动的范围 - 点类型."
我已经了解了按位运算符和两个人的称赞,并且我认为应该对签名数据类型有效,但是它适用于对我没有任何意义的无符号数据类型.这是代码:
#include <stdio.h>
main()
{
signed int i;
i = ~0;
i >>= 1;
printf("Upper limit: %d\n", i);
printf("Lower limit: %d\n", -i -1);
}
Run Code Online (Sandbox Code Playgroud)
这将导致-1被打印为上限,0被打印为下限.但是,如果我将i更改为unsigned int,我会得到我期望的结果(2147483647和-2147483648).我无法解决这个问题,因为我的理解是unsigned int永远不会小于0,而signed int应该使用这些按位运算符,即如果它是32位系统,
~0 == 11111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)
,和
~0 >> 1 == 011111111111111111111111111111111,
or 2147483647.
Run Code Online (Sandbox Code Playgroud)
知道我哪里错了吗?
通过使用%d你对你的价值signed进行处理printf.
你可以%u改用.
添加
正如 Magn3s1um所指出的那样,你不需要指定signed,unsigned因为你的特定任务printf将为你完成所有工作.
输出:
\n\n注意:
\n\xe2\x80\x9c 在表达式 中i >>= 1,负值右移。C 标准说这是一个实现定义的操作,许多实现将其定义为算术移位。在算术移位中,最高有效位保持不变(保持 MSB(有符号位)= 1)”。
(您可以阅读:C 中的右移负数,这>>取决于编译器是否是有符号移位或无正弦移位,但可能在您的情况下它正在执行算术移位。)
为此,在代码之后:
\n\n i = ~0; \n i >>= 1;\nRun Code Online (Sandbox Code Playgroud)\n\ni依然~0。这是二进制 == 11111111111111111111111111111111。
因为~0==11111111111111111111111111111111是 == 2\'c 的补码1 是-1。
因此,当您使用格式字符串打印时,%d它会打印-1. 您应该使用%u打印最大无符号值 == ~0。
这里需要注意的是:
\n\n\n\n\n\xc2\xa76.2.6.2 语言 45、\xc2\xa9ISO/IEC ISO/IEC 9899:201x
\n\n(个\xe2\x80\x99 补码)。其中适用的是\n
\nimplementation-de\xef\xac\x81ned,即是否具有符号位1和\n 所有值位为零(对于\xef\xac\x81 前两个)的值,或者具有符号位和\n 所有值\n 位1(对于\n\n) xe2\x80\x99 补码),是陷阱表示或正常\n 值。在符号和大小以及 1\xe2\x80\x99 补码的情况下,如果\n 此表示是正常值,则称为负零。
您的理解是:
\n\n~0 >> 1 == 011111111111111111111111111111111是错的!(根据输出,它可能会在您的系统中发生,但不会发生)
~0 >> 1 == 111111111111111111111111111111111,注意 MSB(有符号位)是1。
对于无符号移位,请尝试以下操作:
\n\n~0U >> 1 == 011111111111111111111111111111111
注意U未签名的后缀。
第二个 printf:
\n因为i是 -1,所以在第二个表达式-i - 1== - (-1) - 1== 1 - 1==中0,输出为零:0。