C语言中数据是如何存储在内存中的
作者:耀 发布时间:2021-07-03 02:13:34
前言
在计算机内存中,数据的存储方式都是以0和1的形式存储,也就是二进制的形式,数据是如何向内存写入的呢?整形数据以补码的形式存储,浮点型的存储规则较多,类似于科学计数法。
‍数据类型介绍
为什么需要有这些数据类型?
数据类型解决了数据存储的问题。
‍整形数据在内存中存储
整数中有三种二进制表示形式,分别是原码、反码、补码,正整数的原码 = 反码 = 补码,通常取最高位作为符号位。
原码:直接将正负整数按照二进制形式转换即可。
15原码: (0) 1111
-15原码: (1) 1111
23原码: (0) 10111
-28原码: (1) 11100
注意:()表示符号位,1表示负,0表示正。
补码:负整数的补码将原码的符号位不变,其它位依次取反。
15反码: (0) 1111
-15反码: (1) 0000
23反码: (0) 10111
-28反码: (1) 00011
反码:负整数的反码在补码的基础上+1
15补码: (0) 1111
-15补码: (1) 0001
23补码: (0) 11000
-28补码: (1) 00100
对于整形数据来说:数据存放的实际是存放补码。
当我们定义变量时,系统会根据变量的数据类型,给变量开辟空间。这也是为什么要引入数据类型这个概念。
1.举例:5是如何存储到内存中
5是一个整形常量,在C语言中写一个整形常量,不超过int类型所能表示的范围,以32位表示整形常量。
5的原码码 = 补码 = 反码
5原码:00000000 00000000 00000000 00000101
5存入short类型的变量:取后16位
00000000 00000000 00000000 00000101
5存入int类型的变量:取32位
00000000 00000000 00000000 00000101
2.举例:-10是如何存储到内存中的
-10原码:10000000 00000000 00000000 00001010
-10反码:11111111 11111111 11111111 11110101
-10补码:11111111 11111111 11111111 11110110
-10存入short类型:取后16位
11111111 11111111 11111111 11110110
-10存入int类型变量:取32位
11111111 11111111 11111111 11110110
如何取出数据?
取出数据首先要知道数据的地址,得到地址后,如何确定取出范围,由变量的数据类型来决定。
int main()
{
/*
a的原码、反码、补码:00000000 10011000 10010110 1000000
*/
int a = 10000000;
/*
b是short*类型,解引用访问时,只有访问两个字节的权限
*b拿出的数据是补码: 10010110 10000000->原码:11101001 10000000
*/
short* b = &a;
printf("%d", *b);//-27008
return 0;
}
为什么要使用补码的形式存储?
在计算机中CPU有中,只有加法器。以补码形式存储,符号位参与运算,既可以计算减法也可以计算加法。
大端存储模式:指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。
小端存储模式:指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。
大小端主要由处理器决定,与编译器,操作系统这些没有直接的关系。
‍浮点型数据在内存存储
根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)S*M*2^E
(-1)S表示符号位,当S = 0,V为正数;S = -1,V为负数
M表示有效数值,大于等于1,小于2
2^E表示指数位
类似于科学计数法:1090 = 1.090*10^3
IEEE754规定单精度浮点型和双精度浮点型存储模型
IEEE 754对有效数字M和指数E,还有一些特别的规定。
1<=M<2,M可以写成1.xxxxxx的形式,xxxxxx表示小数部分。
IEEE754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以舍去,只保存后面的xxxxxx部分。在读取时,再把第一位添上。节省一位有效数字.
对于指数E,情况比较多。
首先E为无符号整数,如果E为八位,取值范围时0~255,E为11位,取值范围为0~2047,但是再科学计数法中E可以出现负数,所以IEEE 754则规定,存入内存E的真实数必须加上一个中间数,对于八位的E,中间数为127,对于11位的E,中间数位1023。例如2^13的E是13,所以在保存E时,必须保存成13+127 = 140,即10001100。
指数E从内存中取出还可以分为3种情况
1.E不全为0或不全为1
这时浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
比如:
0.5的二进制位0.1,由于规定整数部分1<=M<2,即第一位必须位1,则将小数点右移一位,则为1.0*2^(-1),E的实际存储位-1+127,E的实际存储为01111110,M = 1.0,小数部分为0,M的存储为23位00000000000000000000000。
则0.5的二进制表示形式位:
0 01111110 00000000 00000000 0000000
2.E全为0
这时,浮点数的指数E等于1-127(或者1-1023),即为真实值
有效数字M不再加上第一位的1,而是还原位0.xxxxxx的小数,这样可以表示0,以及接近于0的很小数字。
3.E全为1
如果有效数字M全位0,表示无穷大。
举例:
10.0转化为二进制形式为1010.0,相当于:1.010*2^3,按照标准格式 可得S = 0,M = 1.010,E = 3。
举例1:7.25是如何存储到内存中的呢?
首先将7.25转化为二进制111.01
写成标准形式:1.1101*2^2
S = 0,M = 1101,E = 2+127
0 10000001 11010000 00000000 0000000
验证:
有误的地方还请批评指正。
来源:https://blog.csdn.net/qq_52763385/article/details/124111982


猜你喜欢
- 前言:使用 interrupt 来通知线程停止运行,而不是强制停止!普通情况停止线程public class Right
- 1、系统信息:Windows10 64位2、环境搭建参考:https://www.jb51.net/article/185086.htm3、
- 1.图集导航1.1 为什么对包名的命名要有所规范呢!使用规范的命名有益于程序的开发和后期阅读通俗的说:就是自己写的代码别人也能看的懂,代码结
- 最近由于编程的需要,对 C# 的类型转换做了一些研究,其内容涉及 C# 的装箱/拆箱/别名、数值类型间相互转换、字符的 ASCII 码和 U
- 1. xml文件中加入自定义 搜索view<com.etoury.etoury.ui.view.IconCenterEditText
- 作为Android基础组件之一,大家对viewpager已经很熟悉了,网上也有很多使用viewpager来加载图片的案例。但是像微信那样点击
- 如果我们在Intellij Idea中开发好程序,需要部署到远程SSH服务器运行,我们可以使用某些SSH软件的rz功能,也可以使用专用的FT
- •readonly和const都是用来标识常量的[1]。•const可用于修饰class的field或者一个局部变量(local varia
- 先说下 需要的依赖包<dependency> <groupId>org.ap
- response.setHeader设置下载文件名无效response.setContentType("application/o
- 泛型将集合中的元素限定为一个特定的类型。术语ArrayList<E> -- 泛型类型ArrayList -- 原始类型E --
- 这篇文章讨论了Java面向对象概念中一个基本的概念–Field Hiding(隐藏成员变量)在讨论这个问题之前,我们看一段特别特别简单的代码
- 本文实例讲述了C#中datagridview使用tooltip控件显示单元格内容的方法。分享给大家供大家参考,具体如下:代码如下:using
- 一、概述VideoView类将视频的显示和控制集于一身,我们可以借助它完成一个简易的视频播放器。VideoView和MediaPlayer也
- 1.分支结构的概念当需要进行条件判断并做出选择时,使用分支结构2.if分支结构格式:if(条件表达式){语句块;}package com.l
- 最近项目上产品经理提了个需求,要求关闭语言国际化,不管手机系统设置那个国家的语言,都要显示汉语,好吧,既然有需求,那就做吧。但是项目中已经有
- 人人客户端有一个特效还是挺吸引人的,在主界面手指向右滑动,就可以将菜单展示出来,而主界面会被隐藏大部分,但是仍有左侧的一小部分同菜单一起展示
- 一,Maven 依赖 pom.xml配置1, 去掉默认日志,以便切换到log4j2的日志依赖2, 然后添加如下两个日志依赖二,在工程根目录下
- CopyOnWriteArrayList介绍它相当于线程安全的ArrayList。和ArrayList一样,它是个可变数组;但是和Array
- 根据条件改变DataGridView行的颜色可以使用RowPrePaint事件。示例程序界面如下:示例程序代码如下:using System