0%

编写程序确定有符号和无符号型的各类型变量的取值范围

文章时效性提示

本文发布于 471 天前,部分信息可能已经改变,请注意甄别。

《C程序设计语言》练习2-1
编写一个程序以确定分别由signed及unsigned限定的char、short、int及long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现。后一种方法的实现较困难一些,因为要确定各种浮点类型的取值范围。

思路:

  1. 先把数字0的二进制位进行按位取反,也就是都变成1。
  2. 再把这个二进制数的值转换为unsigned型,并右移一位来去掉符号位。
  3. 最后转换为有符号型。
    相关:
  4. 按位取反~
  5. 移位操作符
  6. 强制类型转换
  7. 原码、反码、补码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>
    #include <limits.h>
    int main()
    {
        //有符号型
        printf("signed char min = %d\n",-(char)((unsigned char) ~0 >> 1)-1);
        printf("signed char max = %d\n",(char)((unsigned char) ~0 >> 1));
        printf("signed short min = %d\n",-(short)((unsigned short) ~0 >> 1)-1);
        printf("signed short max = %d\n",(short)((unsigned short) ~0 >> 1));
        printf("signed int min = %d\n",-(int)((unsigned int) ~0 >> 1)-1);
        printf("signed int max = %d\n",(int)((unsigned int) ~0 >> 1));
        printf("signed long min = %ld\n",-(long)((unsigned long) ~0 >> 1)-1);
        printf("signed long max = %ld\n",(long)((unsigned long) ~0 >> 1));
        //无符号型
        printf("unsigned char max = %u\n",(unsigned char) ~0);
        printf("unsigned short max = %u\n",(unsigned short) ~0);
        printf("unsigned int max = %u\n",(unsigned int) ~0);
        printf("unsigned long max = %lu\n",(unsigned long) ~0);
        return 0;
    }
    以上面的char型为例,char型是由8位二进制数组成的:
    (char)((unsigned char) ~0 >> 1)
    ~0把数字0进行按位取反,也就是把0000 0000变为1111 1111。
    再把~0转换为无符号型:(unsigned char) ~0,这一步是为了下面的右移操作。
    把这个无符号型的二进制数右移,去掉符号位。即0111 1111:(unsigned char) ~0 >> 1
    最后,把unsigned char型转换为char型,也就是signed char型:(char)((unsigned char) ~0 >> 1)

对于char型的最小值,要在前面最大值的基础上取反再减1。

char、signed char和unsigned char的区别

在C标准中没有规定char是signed char还是unsigned char,主要取决于编译器。
但一般而言,未指定的数据类型均为signed,如int、char等价于signed int、signed char。
如果想要定义无符号类型,需要在前面加上unsigned。

为什么最小值要在最大值的基础上取反再减1?

以char型为例,就是一个占8位的二进制数,去掉符号位,数值位还有7位二进制数。
0-127的二进制表示是从00000000~01111111,全都是0开头的,0是代表正数的符号位,而-128~-1的补码表示为10000000-11111111,全是1开头的,所以1是代表负数的符号位。