计算C中数据类型的范围

时间:2013-07-22 19:42:03

标签: c

我正在使用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.

知道我哪里出错了?

5 个答案:

答案 0 :(得分:6)

使用%d,您将值视为signed,以printf继续。

您可以使用%u代替。

<强>加入

正如 Magn3s1um 指出,您无需为特定任务指定signedunsigned printf将为您完成所有工作。

答案 1 :(得分:4)

输出:

  1. 注意:
    “在表达式i >>= 1中,负值向右移动。 C标准说这是一个实现定义的操作,许多实现将它定义为算术移位。在算术移位中,最高有效位保持不变(保持MSB(有符号位)= 1)“。

    (你可以阅读:Right shifting negative numbers in C >>是编译器相关的,无论它是有罪还是无影响的移位,但可能在你的情况下是进行算术移位。)

    出于这个原因,在代码之后:

     i = ~0;  
     i >>= 1;
    

    i仍为~0。这是二进制== 11111111111111111111111111111111

    因为~0 == 111111111111111111111111111111111的= {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

  2. 第二次打印
    由于i-1,因此在第二个表达式中-i - 1 == - (-1) - 1 == 1 - 1 == 0因此输出为零:{{ 1}}。

答案 2 :(得分:3)

您的编译器实现&gt;&gt;算术移位。因此,MSB将其值保持为1,并且移位不执行任何操作。

即,~0&gt;&gt; 1仍然是〜0,因为移位符号延伸。

见这里:https://stackoverflow.com/a/7632/1974021

答案 3 :(得分:3)

您可能会对limits.hfloat.h标题文件

中的常量感兴趣

来自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