C语言的数据存储详解

C语言数据存储

文章目录

  • C语言数据存储
    • 类型的基本归类
      • 类型的意义
    • 数据在内存中的存储
      • 整形在内存中的存储
        • 大小端
        • 整形提升和截断
      • 浮点型在内存中的存储
        • 浮点型的存储规则
          • E的不同情况
        • 运用

类型的基本归类

有无符号的意义:生活中有写数据是没有符号之分的,将最高位(即符号位)利用可以扩大范围

整形包含类型占用空间备注
charunsigned char1Byte字符的本质是ASCII值,是整形
signed char1Byte不同于直接创建 int a时,a为signed
char1Bytechar 到底是signed 还是 unsigned 标准是未定义的,取决于编译器(VS下为signed)
shortunsigned short (int)2Bytes
(signed) short (int)2Bytes
intunsigned int4Bytes
(signed) int4Bytes
longunsigned long (int)4/8BytesC语言在规定类型大小时,只规定了 sizeof(long) >= sizeof(int)
(signed) long (int)4/8Byteslong 在x86为4,x64为8
long longunsigned long long (int)8Byteslong long 为C99中引入
(signed) long long (int)8Bytes
浮点型占用空间备注
float4Bytesfloat 的精度低,存储范围小,double 精度高,范围大
double8Bytes
long double不定长度可能会应编译器和平台的不同而产生差异,可能和 double 一样长,可能更长(8/12/16Bytes)

long double 在 C99 标准中被引入,用以表示更高精度的浮点数

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

以及不同类型所对应的指针类型、空类型(void)

空类型常用于函数的返回类型(表示无返回)、函数的参数(无需参数)等

类型的意义

  • 不同的类型对应所开辟的内存空间大小不同(内存大小决定使用范围)
  • 程序看待对应内存空间的视角(程序以何种规则读取)

以下程序用于验证整形和浮点型的存取规则不同

#include <stdio.h>

int main()
{
    int n = 9;//开辟4bytes
    float* pFloat = (float*)&n;//把n的地址放到pfloat里面,实际还是指向那整形的4bytes

    printf("n的值为:%d\n", n);//9
    printf("*pFloat的值为:%f\n", *pFloat);//0.000000
    //这里按照浮点的规则取出数据,结果错误,说明整形和浮点的存储方式不同

    *pFloat = 9.0;
    printf("num的值为:%d\n", n);//1,091,567,616
    printf("*pFloat的值为:%f\n", *pFloat);//9.000000
    return 0;
}

数据在内存中的存储

整形在内存中的存储

整形表示的范围在limits.h中定义(如果不用到上限和下限的话不用引)

在这里插入图片描述

在这里插入图片描述

程序中整形的二进制表示方式有三种,分别为原码、反码和补码

  • 原码即为整数的二进制表示,对于有符号类型,最高位为符号位,0表示正数,1表示负数
  • 正数的三码相同
  • 负数的反码为原码按位取反(最高位不变),补码为反码加1

以7和-7为例(int)

整形表示方式数据
7原码00000000 00000000 00000000 00000111
反码00000000 00000000 00000000 00000111
补码00000000 00000000 00000000 00000111
-7原码10000000 00000000 00000000 00000111
反码11111111 11111111 11111111 11111000
补码11111111 11111111 11111111 11111001

在计算机系统中,数值一律用补码来表示和存储。通过补码,可以将负数视为正数,将加法和减法统一处理(CPU只有加法器)此外,补码与原码相互转换(补码的补码即为原码),其运算过程是相同的,不需要额外的硬件电路

int main()
{
    int a = 20;
    //原、反、补:00000000 00000000 00000000 00010100
    //    十六进制      00       00       00       14  (0x 00 00 00 14)

    int b = -10;
    //最高位为符号位
    //原:10000000 00000000 00000000 00001010
    // 0x 80       00        00         0a
    //反:11111111 11111111 11111111 11110101
    // 0x ff        ff        ff         f5
    //补:11111111 11111111 11111111 11110110
    // 0x ff        ff        ff         f6
    //对补码取反:
    //      10000000 00000000 00000000 00001001
    // +1:
    //      10000000 00000000 00000000 00001010 得到原码

    //20-10 = 20 + (-10)
    int c = a + b;
    //00000000 00000000 00000000 00010100
    //11111111 11111111 11111111 11110110
    //相加得到一个补码:
    //(1)00000000 00000000 00000000 00001010 最高位被丢掉
    //0x 00 00 00 0a  (10)
    return 0;
}
大小端

大小端即计算机系统中两种不同的数据存储方式

大端存储模式 将数据的低位保存在内存中的高位地址,将数据的高位保存在低位地址

小端存储模式 将数据的低位保存在内存中的低位地址,将数据的高位保存在高位地址

由于数据长度、寄存器大小不同,且计算机的存储是以字节为单位的,这就导致了不同长短的数据和寄存器(如16位、32位)之间存在数据存放的顺序问题(即哪些数据放在高地址,哪些放在低地址),大小端存储模式就是为了解决这类问题

我们常用的X86(x64) 结构是小端模式

这里以上面这段简单的代码为例,以下分别位a,b在内存中的存储

在这里插入图片描述

在这里插入图片描述

实际上,数据存储的规则可以是多种的,只要保证存入和取出的方式相同即可

浮点型同样有大小端,但对一个字节的数据,没有顺序可谈

//判断当前环境是大端还是小端
#include <stdio.h>
int check()
{
    int i = 1;
    return (*(char*)&i);
    //将地址强制转为char*,即只读取最低位的数据
    //当为小端,得到1;当为大端,得到0
}
int main()
{
    int ret = check();
    if (ret == 1)
    {
        printf("小端\n");
    }
    else
    { 
        printf("大端\n");
    }
    return 0;
}
整形提升和截断

截断发生在数据存储时,整形提升发生在使用时

有关整形提升和截断的内容,详见另一篇博客

C语言对类型的转换-CSDN博客

#include <stdio.h>
int main()
{
    char a = -1;
    //char 在VS下是有符号的

    // -1 是整形,为32位,要存入char,要发生截断
    //原:10000000 00000000 00000000 00000001
    //反:11111111 11111111 11111111 11111110
    //补:11111111 11111111 11111111 11111111
    //发生截断
    // a -- 11111111
    // %d 打印有符号整形,发生整形提升,对于有符号数,高位补1
    // 11111111 11111111 11111111 11111111 -- 补码
    // 10000000 00000000 00000000 00000000 -- 取反
    // 10000000 00000000 00000000 00000001 -- +1 得到原码
    // b的打印同理
    // 截断和大小端无关,相当于是从内存中拿出数据后再发生截断

    signed char b = -1;

    unsigned char c = -1;
    //原:10000000 00000000 00000000 00000000
    //反:11111111 11111111 11111111 11111110
    //补:11111111 11111111 11111111 11111111
    // c -- 11111111
    //无符号数高位补0
    // 00000000 00000000 00000000 11111111 --- 直接就是原码

    printf("a=%d,b=%d,c=%d", a, b, c);
    //VS环境下打印  a=-1,b=-1,c=255
    return 0;
}

浮点型在内存中的存储

根据国际标准IEEE(电气和电子工程协会) 754 (即IEEE二进制浮点数算术标准),任意一个二进制浮点数V可以表示成下面的形式:

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

(-1)^s — 符号位,当s=0,V为正数;当s=1,V为负数

M — 有效数字,大于等于1,小于2

2^E — 指数位

6.0的二进制表示就是 110.0

s=0,M=1.1,E=2

即为1.1×2^2

6.5就是110.1

s=0, M=1.101,E=2

即为1.101×2^2

浮点型的存储规则

float - 4bytes - 32 bit

最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M

double - 8bytes - 64bit

最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M

根据十进制转换二进制的计算规则(小数部分×2取整,得0为止)可知,当一个数的小数部分在多次乘法取整后仍不为0时,可能会将有效数字所占长度全部使用,后面的数据将无法存储。即浮点数存在丢失精度的情况

IEEE 754规定,在计算机内部保存M时,默认的第一位总是1,因此可以被舍去,只保存后面的小数部分(即保留24/53位有效数字),由此可以提高精度

E为一个无符号整数(unsigned int),当8为8位时,其范围为0~255,而科学计数法中的指数可以存在负数,因此IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,即加上127/1023

E的不同情况
  • E不全为0或不全为1

    此时,E的真实值计算即为(E-中间值)

  • E全为0

    E+127 = 0,这时,浮点数的指数E等于1-127(或者1-1023)即为真实值

    有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于

    0的很小的数字

  • E全为1

    E + 127 = 255

    这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)即 1.xxxxxx * 2^128


运用

利用这些规则,分析上面的代码

#include <stdio.h>

int main()
{
    int n = 9;
    //00000000 00000000 00000000 00001001
    //0 00000000 00000000000000000001001
    //s=0 E=00000000

    float* pFloat = (float*)&n;

    printf("n的值为:%d\n", n);//9
    printf("*pFloat的值为:%f\n", *pFloat);//0.000000
    //0 00000000 0000000000 0000000001 001
    //s=0 E=00000000
    //一个接近0的很小的数


    *pFloat = 9.0;
    //9.0 --- 1001.0
    //s=0 E=3 --- 00000011
    // 3 + 127 = 130 --- 1000 0010
    //0 10000010 0010000000 0000000000 000
    printf("num的值为:%d\n", n);//1,091,567,616

    //01000001 00010000 00000000 00000000
    printf("*pFloat的值为:%f\n", *pFloat);//9.000000
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/419201.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DolphinScheduler——蔚来汽车数据治理开发平台的应用改造

目录 一、业务痛点 二、应用现状 三、技术改造 3.1 稳定性 3.1.1 滚动重启黑名单机制精准路由 3.2 易用性 依赖节点优化 补数任务优化 多 SQL 执行 原文大佬的这篇基于调度系统的数据治理案例有借鉴意义&#xff0c;这里摘抄下来用作学习和知识沉淀。 一、业务痛点 蔚…

lazada、速卖通、亚马逊店铺需要补单来稳定出单率吗?

亚马逊、速卖通、Lazada、shoppe、速卖通、敦煌网、Temu、shein、阿里国际、卖家如何保证店铺出单稳定?在竞争激烈的平台上&#xff0c;保持店铺的稳定出单是每个卖家都追求的目标。为了实现这一目标&#xff0c;卖家需要综合考虑产品、运营、客户服务等多个方面的因素&#x…

刘志雄:新产品市场+新智造模式,构建“声音+”产业创新生态 | 演讲嘉宾公布

随着科技的飞速发展&#xff0c;新技术、新的应用场景不断涌现&#xff0c;也影响着“声音”产业未来的发展方向。如何应对市场变化&#xff0c;满足市场的多样化需求&#xff1f;如何应用新产品市场、智造新模式去构造“声音”产业创新生态呢&#xff1f;请到GAS2024一探究竟。…

ElasticSearch之Completion Suggester

写在前面 通过completion suggester可以实现如下的效果&#xff1a; 其实就是做的like xxx%这种。通过FST这种数据结构来存储&#xff0c;实现快速的前缀匹配&#xff0c;并且可以将es所有的数据加载到内存中所以速度completion的查询速度非常快。 需要注意&#xff0c;如果…

2024最新版,Android开发教程入门

真正最能锻炼能力的便是直接去阅读源码&#xff0c;不仅限于阅读Android系统源码&#xff0c;还包括各种优秀的开源库。 由于整个文档比较全面&#xff0c;内容比较多&#xff0c;篇幅不允许&#xff0c;下面以截图方式展示 。 深入解析微信 MMKV 源码 初始化获取修改删除读取…

利用Quartz实现复杂的任务调度

第一章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;任务调度&#xff0c;简而言之&#xff0c;就是按照预定计划自动执行任务的过程。不管是数据库备份、报表生成还是发送定时邮件&#xff0c;它们都需要一个可靠的任务调度系统来保证按时完成。 那么&#xff0…

【学习笔记】深度学习实战 | LeNet

简要声明 学习相关网址 [双语字幕]吴恩达深度学习deeplearning.aiPapers With CodeDatasets 深度学习网络基于PyTorch学习架构&#xff0c;代码测试可跑。本学习笔记单纯是为了能对学到的内容有更深入的理解&#xff0c;如果有错误的地方&#xff0c;恳请包容和指正。 参考文献…

基于ssm网络办公系统论文

摘 要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔阂给消除了&#xff0c;让整个世界都可以即时通话…

【Linux】Linux安装

Linux安装&#xff08;保姆级教程&#xff09; 准备工具下载链接 Linux镜像系统官网&#xff08;Centos版本&#xff09;&#xff1a;https://www.centos.org/ 虚拟机下载官网&#xff1a;https://www.vmware.com 注&#xff1a;Linux是一种系统统称&#xff0c;就像Windows…

小米科技分享:深入解析阿里巴巴面试题之SQL查询

大家好,我是小米,今天要和大家分享的是在阿里巴巴面试中常见的SQL查询题目。SQL查询是数据库领域中的基础,但也是一个非常重要的技能,无论是在面试中还是实际工作中,都有着举足轻重的地位。让我们一起深入了解一下吧! SQL语句的执行过程 首先,我们来了解一下SQL语句的执…

【Java】基本数据类型、包装类与字符串间的转换 例题

写在前面&#xff1a; 关于这道题&#xff0c;初见感觉有点cpu烧坏了&#xff0c;准确来说是看了网上的一些讲解都感觉不尽人意。自己整理了一下&#xff0c;希望能帮助到大家。 题目&#xff1a; 如下两个题目输出结果相同吗&#xff1f;各是什么。 Object o1 true ? new…

悄悄告诉你,干洗店60%业务都在自这里

洗衣管理软件&#xff0c;让生活更轻松&#xff01;无论是洗衣还是洗鞋&#xff0c;这款软件都能帮你轻松搞定一切&#xff1a;预约、洗涤进度查询、顾客反馈&#xff0c;一切尽在指尖。 店家使用软件智能管理收衣收鞋&#xff0c;从接收、洗涤到通知顾客取衣&#xff0c;全程自…

【UE 材质】制作加载图案(2)

在上一篇&#xff08;【UE 材质】制作加载图案&#xff09;基础上继续实现如下效果的加载图案 效果 步骤 1. 复制一份上一篇制作的材质并打开 2. 添加“Floor”节点向下取整 除相同的平铺数 此时的效果如下 删除如下节点 通过“Ceil”向上取整&#xff0c;参数“Tiling”默认…

4、正则表达式、本地存储

一、正则表达式 1、定义 用事先定义好的一些特定字符&#xff0c;这样的字符组合&#xff0c;组合成一个“规则字符串” 2、正则的组成 特殊字符 字母、数字、下划线、中文、特殊字符… 元字符&#xff08;常用&#xff09; 1、\d 匹配至少有一个数字 var reg /\d/ /…

东莞IBM服务器维修之IBM x3630 M4阵列恢复

记录东莞某抖音电商公司送修一台IBM SYSTEM X3630 M4文档服务器RAID6故障导致数据丢失的恢复案例 时间&#xff1a;2024年02月20日&#xff0c; 服务器品牌&#xff1a;IBM System x3630 M4&#xff0c;阵列卡用的是DELL PERC H730P 服务器用途和用户位置&#xff1a;某抖音电…

新品齐发!小牛电动打造全场景高端化产品阵列!

2 月 29 日&#xff0c;全球智能城市出行品牌小牛电动发布“新世代性能旗舰”电摩NX、电自NXT&#xff0c;以及“全场景智驾越野电摩”X3三款新品。同时&#xff0c;与知名体育电竞俱乐部——JDG京东电子竞技俱乐部携手&#xff0c;打造“英雄的联盟”超级形象&#xff0c;引领…

文件误删除怎么恢复?盘点4个有效方法!

“我有一些很重要的工作文件保存在电脑上了&#xff0c;但是刚刚操作的时候却发现有些文件被误删了。有什么简单的误删文件恢复方法吗&#xff1f;” 在日常生活和工作中&#xff0c;我们可能都需要在电脑上保存各种各样的文件。如果在操作时误删比较重要的文件&#xff0c;很多…

进阶了解C++(4)——多态

在上篇文章中&#xff0c;简单的介绍了多态中的概念以及其相关原理。本文将针对多态中其他的概念进一步进行介绍&#xff0c;并且更加深入的介绍关于多态的相关原理。 目录 1. 抽象类&#xff1a; 2. 再谈虚表&#xff1a; 3. 多继承中的虚函数表&#xff1a; 1. 抽象类&am…

Mybatis-Plus介绍

目录 一、Mybatis-Plus简介 1.1、介绍 1.2、特性 1.3、架构 1.4、Mybatis-Plus与Mybatis的区别 二、快速入门 2.1、首先创建数据库mybatis-plus 2.2、创建user表 2.3、插入数据 2.4、创建Spring-Boot项目 2.5、添加依赖 2.6、连接数据库 一、Mybatis-Plus简介 1.1、…

Springboot项目集成短信验证码(超简单)

操作流程 注册验证码平台创建验证码模版开始集成&#xff08;无需引入第三方库&#xff09; 注册并登陆中昱维信验证码平台 获取AppID和AppKey。 创建验证码模版 创建验证码模版&#xff0c;获取验证码模版id 开始集成 创建controller import org.springframework.web.bi…