【C语言进阶】1. 数据的存储

1.数据类型的介绍

【C语言进阶】1. 数据的存储_第1张图片
long 长整型 4/8个字节
在C语言的定义中只规定了sizeof(long)>=sizeof(int)
在32位平台long为4个字节,在64位平台int为8个字节
类型的意义
1.使用这个类型所开辟的内存空间
2.如何看待内存空间的视角
int/float类型都是4个字节但是内存布局不一样

1.1数据类型的划分

【C语言进阶】1. 数据的存储_第2张图片
char 到底是signed char 还是unsigned char 标准是未定义的,取决于编译器。
short、int、long、long long这些都是signed 类型(有符号类型)
有无符号的区别:
有符号,符号位0表示是正数,符号位1表示是负数。
无符号,第一位也是数值位为1表示2^31。
【C语言进阶】1. 数据的存储_第3张图片
【C语言进阶】1. 数据的存储_第4张图片
int [ 5 ] /int [ 8 ] …都是不同类型
【C语言进阶】1. 数据的存储_第5张图片【C语言进阶】1. 数据的存储_第6张图片

2.整型在内存中的存储

一个变量的创建是需要在内存中开辟空间的,空间的大小是根据不同类型来决定的。

2.1 原码、反码、补码

【C语言进阶】1. 数据的存储_第7张图片
0b表示二进制 0表示八进制 0x表示16进制
【C语言进阶】1. 数据的存储_第8张图片
【C语言进阶】1. 数据的存储_第9张图片
数据在内存中存储是以二进制的形式,这些0x只是为了方便在内存窗口观察
整数在内存中的存储是补码的形式
【C语言进阶】1. 数据的存储_第10张图片
【C语言进阶】1. 数据的存储_第11张图片
如果计算机以原码的形式存储 -1+1计算结果为-2,明显不正确 而以补码的形式存储计算结果就是0
补码与原码的相互转换,其运算过程是相同的
原码得到补码取反加1;补码得到原码取反加1;

2.2 大小端的介绍

【C语言进阶】1. 数据的存储_第12张图片
数据在内存中的存储形式可以是五花八门的,只要能从内存中取出数据即可,但是奇奇怪怪的方式并不适合计算机取出数据,于是就保留下来两种方式大端存储,小端存储
【C语言进阶】1. 数据的存储_第13张图片
这里的11 22 33 44只是为了方便表示,实际上数据在内存中还是以二进制进行存储
【C语言进阶】1. 数据的存储_第14张图片
通过代码来判断计算机是大端字节序还是小端字节序
【C语言进阶】1. 数据的存储_第15张图片
小端:0x 01 00 00 00 大端:0x 00 00 00 01
取出a的地址 int 类型 一次访问四个字节,进行强制类型转换 char* 取出的是第一个字节的地址再解引用判断大端小端
不管是浮点型还是整型只要是有多个字节的,就存在大小端字节序
【C语言进阶】1. 数据的存储_第16张图片
signed char -127~128(10000000不用计算原反补,直接当做-128)
unsigned char 0~255

2.3 练习

1.

【C语言进阶】1. 数据的存储_第17张图片
打印出来的是-1,-1,255
-1在内存中存储形式为补码:11111111111111111111111111111111
将-1放入char中会发生截断(截断都发生在存储过程)
a,b中存放的就是:11111111(补码形式)
又要将a,b以%d的形式打印出来发生整型提升
a,b都是有符号类型(符号位为1)全补1
11111111111111111111111111111111(补码)
转换成原码就是-1
c中同样存放的是11111111 发生整形提升,c是unsigned 所以全补0
认为其是正数 原反补相同,所以打印出来为255
这里的截断与大小端无关,(隐式类型转换)只是将int类型的最后几位截取后存放到char类型变量当中
大小端是指在内存中存储的字节序形式

2.

【C语言进阶】1. 数据的存储_第18张图片
整型提升全补1以%u的形式打印出来数值很大
在这里插入图片描述

3.

【C语言进阶】1. 数据的存储_第19张图片
给char类型赋值128时, 截取得到的还是10000000
所以在进行整型提升时,char是有符号类型的,符号位为1,全补1
在这里插入图片描述
结果与上面2题相同

4.

【C语言进阶】1. 数据的存储_第20张图片
unsigned int类型与int类型相加 会自动发生类型转换 转化成unsigned int类型 但是这里的printf打印形式是以有符号整型的形式打印
将1111111111111111111110110看做补码,就是负数的形式(要进行原反补的转化),结果就是 - 10

5.

判断打印出来的是什么?
【C语言进阶】1. 数据的存储_第21张图片
【C语言进阶】1. 数据的存储_第22张图片
i 是无符号整型,所以所有的二进制位都是有效位 9~0,0-1 就是-1
-1是以补码的形式存放在内存中全为1,-1以无符号整型表示是很大的数字
i永远不会小于0,所以就是一直死循环的状态。
【C语言进阶】1. 数据的存储_第23张图片

6.

【C语言进阶】1. 数据的存储_第24张图片
如果不加思索,-1,-2,-3,-4…-1000
循环1000次
但是数组当中的元素是char类型
char的范围是-128~127
表达式 a[ i ](char) = -1 - i (int);会发生截断
【C语言进阶】1. 数据的存储_第25张图片
【C语言进阶】1. 数据的存储_第26张图片
【C语言进阶】1. 数据的存储_第27张图片
所以strlen算出的长度应该为255

7.

【C语言进阶】1. 数据的存储_第28张图片
当unsigned char 为255时 再加一又变为0 ,所以也是死循环

8.

【C语言进阶】1. 数据的存储_第29张图片
在C语言定义当中strlen返回值是size_t类型
size_t 就是unsigned int
因为计算字符串长度是不可能返回负数的,所以设计成无符号整型
两个strlen进行相减,返回的也是无符号整型,所以恒大于0 只可能打印出>
而采用my_strlen 模拟函数,返回值是int类型,则不会出现上述的情况(各有利弊)

3.浮点数在内存中的存储(重点)

常见的浮点数:
3.14159
1E10
浮点数家族包括: float、double、long double 类型。
浮点数表示的范围:float.h中定义(整型的定义在limits.h当中)
1E10 就是1.0*1010 科学计数法

3.1 一个例子

【C语言进阶】1. 数据的存储_第30张图片
将int类型的地址类型转换成float的形式 分别以整型和浮点数的形式取出
将n中的值修改为9.0浮点数类型 分别以整型和浮点数的形式取出
如果浮点数和整型在内存中的存储形式是一致的,那么打印出来的将是9 , 9.0 , 9 , 9.0
但是结果如下
【C语言进阶】1. 数据的存储_第31张图片
这个案例说明了浮点数与整型在内存中的存储形式不一样

3.2 浮点数存储规则

浮点数的二进制表示:
【C语言进阶】1. 数据的存储_第32张图片
【C语言进阶】1. 数据的存储_第33张图片
【C语言进阶】1. 数据的存储_第34张图片
小数点后面的位置从2-1 ,2-2 … 所以,小数点第一位是0.5 ,第二位是0.125. …
【C语言进阶】1. 数据的存储_第35张图片
如果存储类似于9.6的浮点数,那么可能永远无法精确的表示出 .6这小数点位,而且float(double)类型只有32(64)个比特位
无法存放下后面的数字,导致精度丢失
浮点数在内存中无法精确保存
【C语言进阶】1. 数据的存储_第36张图片
【C语言进阶】1. 数据的存储_第37张图片
【C语言进阶】1. 数据的存储_第38张图片
【C语言进阶】1. 数据的存储_第39张图片
【C语言进阶】1. 数据的存储_第40张图片
【C语言进阶】1. 数据的存储_第41张图片
f在内存中的存储形式

取出情况
【C语言进阶】1. 数据的存储_第42张图片
【C语言进阶】1. 数据的存储_第43张图片
当E为全0时,真实值为-126或者-1022 , xxxxx*2-126这是非常小的,232 已经是42亿
【C语言进阶】1. 数据的存储_第44张图片
同理,全1就是+126 ,就是存储非常大的数值

3.3 解释上面例子

【C语言进阶】1. 数据的存储_第45张图片
【C语言进阶】1. 数据的存储_第46张图片

你可能感兴趣的:(C语言进阶,c语言)