0%

数据的存储

文章时效性提示

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

数据的类型

char字符数据类型
short短整型
int整型
long长整型
long long更长的整型
float单精度浮点型
double双精度浮点型

C语言数据类型分为两类:内置类型,就是上面的类型,和自定义类型(构造类型)。

类型的意义:

  • 使用这个类型开辟内存空间的大小
  • 如何看待内存空间的视角

类型的基本分类

整型家族:

char

  • unsigned char
  • signed char

short

  • unsigned short [int]
  • signed short [int]

int

  • unsigned int
  • signed int

long

  • unsigned long [int]
  • signed long [int]

[int]:这个可以省略

浮点型家族

float 单精度浮点型
double 双精度浮点型

构造类型

数组类型
结构体类型 struct
枚举类型 enum
联合类型 union

指针类型

1
2
3
4
int* pi
char* pc
float* pf
void* pv

空类型

void表示空类型(无类型)
通常应用于函数的返回类型,函数的参数,指针类型。


整型在内存中的存储

对于整型:在内存中存储的是二进制的补码。

原码、反码、补码

参见:原码、反码、补码

1
2
int a = 20;
int b = -10;

对于a:
原码 - 00000000 00000000 00000000 00010100
反码 - 00000000 00000000 00000000 00010100
补码 - 00000000 00000000 00000000 00010100
在内存中:0x00000014(16进制,根据补码转换)
对于b:
原码 - 10000000 00000000 00000000 00001010
反码 - 11111111 11111111 11111111 11110101
补码 - 11111111 11111111 11111111 11110110
在内存中:0xfffffff6

大小端介绍

什么是大端小端?
大端模式:将数据低位保存在内存高地址中,数据高位保存在内存的低地址中
小端模式:将数据低位保存在内存低地址中,数据高位保存在内存的高地址中

写代码判断当前机器的字节序(判断大端存储还是小端存储):

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main() {
    int a = 1;
    char* p = (char*)&a;
    if(*p == 1)
    {
        printf("小端\n");
    }else
    {
        printf("大端\n");
    }
    return 0;
}

输出什么?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
    char a = -1;
    signed char b = -1;
    unsigned char c = -1;
    printf("a = %d,b = %d,c = %d",a,b,c);
    return 0;
}

输出的结果是:a = -1,b = -1,c = 255
char分为signed char和unsigned char,都是1个字节,8个bit位.
存的是有符号数,内存中最高的位就是符号位
signed char的范围是:-128-127
unsigned char的范围是:0-255

1
2
3
4
5
6
7
#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}

输出的结果是4294967168。
-128的二进制序列:
原码 - 10000000 00000000 00000000 10000000
反码 - 11111111 11111111 11111111 01111111
补码 - 11111111 11111111 11111111 10000000
补码取8比特位:10000000
%u打印10进制无符号数字。
整型提升:11111111 11111111 11111111 10000000(补码)
十进制打印上面的二进制数:4294967168

1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
    int i = -20;
    unsigned int j = 10;
    printf("%d\n",i+j);
    return 0;
}

打印的结果是-10。
先按照补码的形式进行计算,最后格式化成有符号整数。
先计算i:
原码 - 10000000 00000000 00000000 00010100
反码 - 11111111 11111111 11111111 11101011
补码 - 11111111 11111111 11111111 11101100
计算j:(原码、反码、补码一样)
原码 - 00000000 00000000 00000000 00001010
反码 - 00000000 00000000 00000000 00001010
补码 - 00000000 00000000 00000000 00001010
i的反码+j的反码是结果的补码
补码 - 11111111 11111111 11111111 11110110
反码 - 11111111 11111111 11111111 11110101
原码 - 10000000 00000000 00000000 00001010
将结果的原码转换成有符号整数,是-10

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
    unsigned int i;
    for (i = 9; i >= 0; i--) {
        printf("%u\n",i);
    }
    return 0;
}

由于i的类型是unsigned int,i的值永远不会小于0,程序死循环。

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <string.h>
int main()
{
    char a[1000];
    int i;
    for (i = 0; i<1000; i++) {
        a[i] = -1 - i;
    }
    printf("%d",strlen(a));
    return 0;
}

打印的结果是255,因为char只能存255。

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
unsigned char i = 0;
int main()
{
    for (i = 0; i <= 255; i++)
    {
        printf("hello\n");
    }
    return 0;
}

浮点数在内存中的存储

3.14、1E10。
浮点数类型包括float、double、long double类型。

浮点数和整数在计算机中存储的方法是不一样的。

根据IEEE754,二进制浮点数表示方法如下:

1
(-1)^S * M * 2^E

-(1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位

例如计算浮点数9.0:
9.0先转换成二进制形式:1001.0
(-1)^0* 1.001 * 2^3
S=0,M=1.001,E=3。
1<=M<2,M只能是1点几的形式,所以在内存中不保存1,只保留小数部分。

对于32位浮点数,最高位是S,中间8位是E,最后23位是M

对于64位浮点数,最高位是S,中间11位是E,最后52位是M