跳转至

数据的表示

二进制的表示

无符号整数(Unsigned)

如果一个数据表示的位数为w,则可以表示的无符号数据大小范围是[0, 2^w - 1]。下图展示了一个4位比特所能表示的数据范围:

有符号整数(signed)

有符号数据可以表示正数、负数以及0,比特位的最高位表示符号位,若为1则表示负数,若为0则表示非负数。其表示如下图所示:

为什么负数的表示形式是这样的?

首先我们需要知道, -8 + 8 = 0 是大家认可的。大家可以观察下图,可以看到负数的二进制表示是其对应正数的二进制位取反,再加1获得。我们也称有符号数据的表示为补码

数据溢出(overflow)

如果数据超出比特位所能表示的最大值,则会溢出变为所能表示的最小值。

  • example
#include <stdio.h>
#include <limits.h>

int main(){
    // 观察不同数据类型的溢出后的表现
    unsigned int a1 = 0xffffffff;
    int a2 = 0x7fffffff;
    int a3 = 0x80000000;
    // limits.h
    printf("signed int表示最大数值为: %d\n", INT_MAX);
    printf("signed int表示最小数值为: %d\n", INT_MIN);
    printf("unsigned int overflow: %d\n", a1 + 1); // 0
    printf("signed int overflow: %d\n", a2 + 1); // INT_MIN
    printf("int underflow: %d\n", a3 - 1); // INT_MAX

    unsigned short s1 = 0xffff;
    short s2 = 0x7fff;
    short s3 = 0x8000;
    printf("short 表示最大数值为: %hd\n", SHRT_MAX);
    printf("short 表示最小数值为: %hd\n", SHRT_MIN);
    printf("unsigned short overflow: %hu\n", s1 + 1); // 0
    printf("short overflow: %hd\n", s2 + 1); // SHRT_MIN
    printf("short underflow: %hd\n",s3 - 1); // SHRT_MAX

    unsigned char c1 = 0xff;
    char c2 = 0x7f;
    char c3 = 0x80;
    printf("char 表示最大数值为: %hhd\n", SCHAR_MAX);
    printf("char 表示最小数值为: %hhd\n", SCHAR_MIN);
    printf("unsigned char overflow: %hhu\n", c1 + 1); // 0
    printf("char overflow: %hhd\n", c2 + 1); // -128
    printf("char underflow: %hhd\n", c3 - 1); // 127

    return 0;
}
/*
signed int表示最大数值为: 2147483647
signed int表示最小数值为: -2147483648
unsigned int overflow: 0
signed int overflow: -2147483648
int underflow: 2147483647
short 表示最大数值为: 32767
short 表示最小数值为: -32768
unsigned short overflow: 0
short overflow: -32768
short underflow: 32767
char 表示最大数值为: 127
char 表示最小数值为: -128
unsigned char overflow: 0
char overflow: -128
char underflow: 127
*/

位操作

与、或、异或、取反位操作

移位操作

  • 左移操作,右侧比特位填充0
  • 右移操作
  • 逻辑右移,左侧高位填充0
  • 算术右移,左侧高位填充符号位

数据类型的隐式转换

  • C语言中针对同一数据类型的无符号数和有符号数进行大小比较时,会隐式转换为无符号数进行比较

  • 从小数据类型转换为大数据类型

  • unsigned类型添加前导0
  • signed类型添加符号位,符号位为1则添加前导1,符号位为0则添加前导0

  • example

#include <stdio.h>

int main(int argc, char* argv[]){
    short s1 = 4;
    short s2 = -4;

    int i1 = s1;
    int i2 = s2;

    printf("%d\n", i1);
    printf("%d\n", i2);

    return 0;
}

  • 从大数据类型裁剪(truncate)为小数据类型,抛弃超出的高比特位

  • example
#include <stdio.h>

int main(int argc, char* argv[]){
    int x = 53191;
    short sx = x;
    int y = sx;

    // x(4 bytes) binary 0000 0000 0000 0000 1100 1111 1100 0111
    printf("x = %d\n", x); // 53191
    // sx(2 bytes) binary 1100 1111 1100 0111
    printf("sx = %hd\n", sx); // -12345
    // 符号位扩展,前导元素为 1
    // y(4 bytes) binary 1111 1111 1111 1111 1100 1111 1100 0111
    printf("y = %d\n", y); // -12345

    return 0;
}

浮点数的表示

计算机中浮点数主要是用于近似实际中的有理数,它无法精确表示所有数值。1985年IEEE指定了IEEE Standard 754 标准,统一了以往不同的浮点数表示形式。

分数二进制(Fractional Binary Numbers)

分数二进制主要分为两部分,左边的二进制表示整数部分,右边的二进制表示小数部分,如下图所示。

IEEE Floating-Point Representation

浮点数的比特位表示被划分为三个字段: * 符号位 * k位的指数字段 * n位的小数字段

浮点数表示存在两种情况:

  • Case 1: Normalized Values

  • Case 2: Denormalized Values

  • Case 3: Special Values