我正在使用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);
}
这将导致打印-1为上限,0打印为下限。但是,如果我将i更改为unsigned int,我会得到我期望的结果(2147483647和-2147483648)。我无法解决这个问题,因为我的理解是unsigned int永远不会小于0,而signed int应该使用这些按位运算符,即如果它是32位系统,
~0 == 11111111111111111111111111111111
和
~0 >> 1 == 011111111111111111111111111111111,
or 2147483647.
知道我哪里出错了?
答案 0 :(得分:6)
使用%d
,您将值视为signed
,以printf
继续。
您可以使用%u
代替。
<强>加入强>
正如 Magn3s1um 指出,您无需为特定任务指定signed
和unsigned
printf
将为您完成所有工作。
答案 1 :(得分:4)
输出:
注意:强>
“在表达式i >>= 1
中,负值向右移动。 C标准说这是一个实现定义的操作,许多实现将它定义为算术移位。在算术移位中,最高有效位保持不变(保持MSB(有符号位)= 1
)“。
(你可以阅读:Right shifting negative numbers in C >>
是编译器相关的,无论它是有罪还是无影响的移位,但可能在你的情况下是进行算术移位。)
出于这个原因,在代码之后:
i = ~0;
i >>= 1;
i
仍为~0
。这是二进制== 11111111111111111111111111111111
。
因为~0
== 11111111111111111111111111111111
是1
的= {2} c补充-1
。
因此,当您使用格式字符串%d
进行打印时,它会打印-1
。您应该使用%u
打印== ~0
的最大无符号值。
需要注意的重要事项:
§6.2.6.2 Language 45,©ISO / IEC ISO / IEC 9899:201x
(补充)。以下哪项适用
implementation-defined
,与符号位1
和值的值一样 所有值位为零(对于前两个),或者带有符号位和所有值 位1(对于“补码”)是陷阱表示或法线 值。在符号和幅度以及补码的情况下,如果 这种表示是一个正常值,称为负零。
您的理解:
~0 >> 1 == 011111111111111111111111111111111
错了! (根据输出,它可能会在您的系统中发生但不会发生)
~0 >> 1 == 111111111111111111111111111111111
,请注意MSB(已签名位)为1
。
对于无符号班次,请尝试以下操作:
~0U >> 1 == 011111111111111111111111111111111
注意未签名的后缀 U
。
第二次打印:
由于i
为-1
,因此在第二个表达式中-i - 1
== - (-1) - 1
== 1 - 1
== 0
因此输出为零:{{ 1}}。
答案 2 :(得分:3)
您的编译器实现&gt;&gt;算术移位。因此,MSB将其值保持为1,并且移位不执行任何操作。
即,~0&gt;&gt; 1仍然是〜0,因为移位符号延伸。
答案 3 :(得分:3)
来自limits.h
:
+------------+------------------------------------------------------------------+--------------------------------+
| CHAR_BIT | Number of bits in a char object (byte) | 8 or greater |
| SCHAR_MIN | Minimum value for an object of type signed char | -127 (-2^7+1) or less |
| SCHAR_MAX | Maximum value for an object of type signed char | 127 (2^7-1) or greater |
| UCHAR_MAX | Maximum value for an object of type unsigned char | 255 (2^8-1) or greater |
| CHAR_MIN | Minimum value for an object of type char | either SCHAR_MIN or 0 |
| CHAR_MAX | Maximum value for an object of type char | either SCHAR_MAX or UCHAR_MAX |
| MB_LEN_MAX | Maximum number of bytes in a multibyte character, for any locale | 1 or greater |
| SHRT_MIN | Minimum value for an object of type short int | -32767 (-2^15+1) or less |
| SHRT_MAX | Maximum value for an object of type short int | 32767 (2^15-1) or greater |
| USHRT_MAX | Maximum value for an object of type unsigned short int | 65535 (2^16-1) or greater |
| INT_MIN | Minimum value for an object of type int | -32767 (-2^15+1) or less |
| INT_MAX | Maximum value for an object of type int | 32767 (2^15-1) or greater |
| UINT_MAX | Maximum value for an object of type unsigned int | 65535 (2^16-1) or greater |
| LONG_MIN | Minimum value for an object of type long int | -2147483647 (-2^31+1) or less |
| LONG_MAX | Maximum value for an object of type long int | 2147483647 (2^31-1) or greater |
| ULONG_MAX | Maximum value for an object of type unsigned long int | 4294967295 (2^32-1) or greater |
+------------+------------------------------------------------------------------+--------------------------------+
答案 4 :(得分:1)
当您在i
上执行位移时,编译器会看到i
是有符号数量,并执行算术右移。您似乎希望该行代码执行逻辑右移。
更改行
i >>= 1;
到
i = ((unsigned int)i) >> 1;
然后它有效!
Output:
Upper limit: 2147483647
Lower limit: -2147483648