字符型,整形和浮点型在内存中的存储(包含大小端,整形提升,截断)

2024-03-30 12:32

本文主要是介绍字符型,整形和浮点型在内存中的存储(包含大小端,整形提升,截断),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

# 一、字符型

# 二、整形

# 三、浮点型



# 一、字符型

举例 char a = 'A'

字母A所对应的ASCII表二进制形式为01000001.十进制为65.十六进制为41.

一个char类型数据所占的内存是一个字节.(1byte = 8bit)计算机存储数据都是以二进制形式存储。那么&a里存储就是01000001.(注意,字符型不存在反码补码以及大小端序)

 

 为什么char a,signed char b以整形打印出来是-1,unsigned char c打印出来是255呢?先看数据的存储。首先先讲一下原码反码和补码。

原码

直接将二进制按照正负数的形式翻译成二进制

反码

符号位不变,其他按位取反

补码

反码+1得到补码

正数的原码,反码,补码都相同

-1的原码10000000000000000000000000000001

       反码11111111111111111111111111111110(符号位不变,按位取反)

       补码11111111111111111111111111111111(反码+1)

因为char类型只占1byte。所以a,b,c它们的内存中存储的就是补码中低位的8个1。当以整形打印的时候。char类型和signed char都代表有符号字符型,这时候就需要整形提升,按照它们的符号位提升32个比特位。a和b中存储的都是11111111.符号位位1.所以提升完后变成了11111111111111111111111111111111(这是补码形式),要把它变回原码需要先-1,再取反。

11111111111111111111111111111110 -反码

1000000000000000000000000001-原码

所以a和b以%d形式打印结果都为-1.

由于c是无符号字符,它是没有符号位的,所以前面32个比特位全部补0

00000000000000000000000011111111-补码

这时候符号位为0表示正数,正数的原反补码相同。二进制转换结果就是255.

 这里是以%u打印char a。先看a中存储的数据。

-1的原码10000000000000000000000000000001

       反码11111111111111111111111111111110

       补码11111111111111111111111111111111

上面已经讲到过char类型只占一个字节。所以a中存放的是11111111

再看%u。先进行整型提升,a是有符号的字符。按照符号位提升,符号位为1

11111111111111111111111111111111-补码

%u认为这个数据是无符号数,不存在符号位。所以直接二进制转换得到

# 二、整形

int型大家应该都很了解,这里就讲一下unsigned int

 

-1的原码10000000000000000000000000000001

       反码11111111111111111111111111111110

       补码11111111111111111111111111111111

unsigned int a 中存储的就是11111111111111111111111111111111。

以%d打印,第一个1视为符号位,1为负数,转换成原码

11111111111111111111111111111111-补码

11111111111111111111111111111110-反码

10000000000000000000000000000001-原码

二进制转换十进制结果就是-1

以%u打印,就认为a中存得是一个无符号数,没有符号位,直接对11111111111111111111111111111111进行二进制转换,结果为

 再举一个例子

 要想解决这题首先得知道strlen的原理,它会不停读取字符直到读取到‘\0’时停止。那就只需要知道在char a[1000]哪里会存储到第一个‘\0’,先看一下a[0]中存储的是什么

a[0] = -1;

之前已经讲过数据截断。不熟悉的可以回头看一下字符型的几个题目。

&a[0] ->00000001->-1数据截断

&a[1]->00000010->-2数据截断

&a[2]->00000011->-3数据截断

已经需要strlen会在读取到‘\0'时停止,\0对应的ASCII码值为0.那就是要找什么时候a[i]里存得时00000000.8个比特位存储的极限是11111111.转换成十进制是255,当255再+1,266的原码就是

100000000.数据截断存进arr[i]中的就是00000000。现在进行的是-1-i。我们不需要考虑正负的问题,因为数据截断的是低位,只需要让它低8位变成00000000,也就是当-1-i=-256。当i为255,arr[255]中存储就是00000000.0-254一共有255个字符,所以结果为255.

大小端

大端字节序:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中

小段字节序:数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中

举例:

int a = 64

原码反码补码-00000000000000000000000001000000

转换成16进制0x00 00 00 40

0x00D9F824就是a的地址。int一共占四个字节,这里从内存中看到低位到高位的存储顺序是

40 00 00 00.符合了小端字节序,数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中。

# 三、浮点型

浮点数分为两类,32位(float),64位(double)

根据国际标准IEEE(电气和电子工程协会),任意一个二进制浮点数可以表示成:

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

float a = 5.5

小数点后面按2^-1,2^-2计算以此类推。

转换成二进制:101.1 = 1.011*2^2

S:符号位

只存在正负0/1

M:尾数部分

尾数部分只保留小数点后面的部分省略前面的1.。以上面的5.5为例,最后写成1.011*2^2.所有小数的最终形式都是1.xxxxxxxxxxxxx。因此前面的1.可以舍去,这样提高了小数点后的一位精度。

E:指数位

E会有三种情况

E不全为0或不全为1.

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(32位)或1023(64位),得到真实值,再将有效数字M前加上第一位的1.比如0.5的二进制形式位0.1,由于规定正数部分必须位1,即将小数点又移1位,则为1.0*2^-1,其在内存中的表现形式位-1+127=126,表示位01111110,而尾数1.0去掉正数部分为0,补齐0到23位,其二进制形式位:

0 01111110 00000000000000000000000

E全为0

这时,浮点数的指数E等于1-127(或1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxxxxxx的小数。这样做时为了表示正负0,以及无线接近于0的数字。

E全为1

这时,如果有效数字M全为0,表示正负无穷大(正负取决于符号位s)

 

 第一个打印%d为1问题不大。看一下float* p中存得是什么

&a 原码反码补码-00000000000000000000000000000001

当以%f打印时,第一个0为符号位,后8位为指数位,后23位为尾数部分

以%f解读可以看成 0 00000000 00000000000000000000001

此时指数位E全位0.这是一个无线接近于0的负数,所以打印结果为0.000000.

浮点数1.0以%d形式打印

1.0 ->二进制1.0->(-1)^0*1.0*2^0->s=0, m= 1.0, e=0+127=127

-> 0 01111111 00000000000000000000000

以%d来看符号位为0,正数,后面31位时0111111100000000000000000000000.转换为十进制

 最后以%f打印1.0,小数点后默认保留六位,结果为1.000000.

这篇关于字符型,整形和浮点型在内存中的存储(包含大小端,整形提升,截断)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/861493

相关文章

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Oracle存储过程里操作BLOB的字节数据的办法

《Oracle存储过程里操作BLOB的字节数据的办法》该篇文章介绍了如何在Oracle存储过程中操作BLOB的字节数据,作者研究了如何获取BLOB的字节长度、如何使用DBMS_LOB包进行BLOB操作... 目录一、缘由二、办法2.1 基本操作2.2 DBMS_LOB包2.3 字节级操作与RAW数据类型2.

Java实现数据库图片上传与存储功能

《Java实现数据库图片上传与存储功能》在现代的Web开发中,上传图片并将其存储在数据库中是常见的需求之一,本文将介绍如何通过Java实现图片上传,存储到数据库的完整过程,希望对大家有所帮助... 目录1. 项目结构2. 数据库表设计3. 实现图片上传功能3.1 文件上传控制器3.2 图片上传服务4. 实现

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

C语言中的浮点数存储详解

《C语言中的浮点数存储详解》:本文主要介绍C语言中的浮点数存储详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、首先明确一个概念2、接下来,讲解C语言中浮点型数存储的规则2.1、可以将上述公式分为两部分来看2.2、问:十进制小数0.5该如何存储?2.3 浮点

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性