当前位置: 首页 > news >正文

C进阶 数据的存储

目录

前言

一,VS的知识储备

二,有趣的scanf()读取

三,数据的存储 引言

四,整数存储

五,小数存储

总结


前言

这里将深入计算机,看计算机是如何进行数据的存储的,怎么在计算机里面筑巢
为什么会有debug和release两个玩意,太可恶了有时候bebug不行,release可以有时候又反之,知识人性的考研还是计算机的腐败
神奇的scanf在我编写程序与我摩擦出了怎么样的火花
大小端又是一个什么东西,究竟会为什么会改变我对存储的认知


一,VS的知识储备

1,debug和release的区别
两者的主要区别是在于编译的方式,优化等级,预处理器宏定义和运行时库
 debug模式主要运用于调试,适合在开发阶段
release模式主要用于优化代码,提高执行效率,适用发布阶段

1,编译方式
debug模式下编译器会生成的可执行文件中包含调试信息
release模式下编译器会开启多种优化选项,以提高程序的执行效率

2,优化等级
bebug模式会关掉各种优化选项,以便调试程序
release模式会开启各种优化选项,以提高程序的执行效率

3,预处理器的宏定义
debug模式下通常会定义一些预处理器,以便调试程序,而release则不需要
 常用的预处理器宏
 为了区分这两种模式,通常会定义一些预处理器宏。例如:

  • Debug 模式 下,可能会定义 _DEBUGDEBUG

  • Release 模式 下,这些宏通常不会被定义

4,运行时库不一样
debug模式下运行时,库通常是多线程调试版本,而release为多线程,非调试版本,这是也为了减少可执行文件的大小,提高效率

  1. Debug 模式(调试模式)

    • 运行时库:通常是多线程调试版本(如 /MTd/MDd)。这些库包含了调试信息和额外的错误检测机制,例如内存分配检查、缓冲区溢出检测等

    • 特点

      • 包含调试符号信息,便于调试工具加载和使用

      • 生成的可执行文件体积较大,运行速度较慢,但能提供丰富的调试支持

      • 通常会生成 .pdb 文件,用于存储调试信息

  2. Release 模式(发布模式)

    • 运行时库:通常是多线程非调试版本(如 /MT/MD)。这些库不包含调试信息,专注于性能优化

    • 特点

      • 不包含调试符号信息,减少了可执行文件的体积

      • 优化了代码执行效率,提升了程序的运行速度

      • 更适合最终用户使用,因为其体积小、运行速度快

2,X86和X64
X86是32位的X86架构,此架构使用大多数旧的32位windows操作系统和处理器,如果你的应用程序在此平台运行,要选着这个X86架构
X64是64位的X64架构,此架构适用支持64位操作系统于处理器的计算机,X64无法在32位操作系统运型,但是可以又更大空间进行操作

  • 32位和64位架构的区别

    • 地址空间:64位架构支持更大的地址空间

    • 寄存器数量和宽度:64位架构有更多的寄存器,寄存器宽度更大

    • 指令集:64位架构支持更复杂的指令集

    • 性能和效率:64位架构通常更适合高性能计算和大数据处理

    • 栈空间:64位系统可以支持更大的栈空间,但默认的栈大小并不一定比32位系统大

二,有趣的scanf()读取

我在使用scanf的时候遇到了这个问题

我想正常的输入一个带有空格的字符串,但是最后打印出来只有一个I,我的LOVE YOU没有了,是因为scanf扫描到I后面的空格的时候就忽略了后面的LOVE YOU


scanf() 在读取字符串得时遇到空白字符串(空格,制表符和换行符)时会停止读取,并将剩下的字符(包括换行字符)留在stdin输入流里面(不是键盘缓冲区)

#include <stdio.h>                                                                
#include <windows.h>                                                             
int main(void){                                                                   
    char str[80], str1[80], str2[80];                                           
    scanf("%s",str);/*此处输入:I love you!*/                                    
    printf("%s\n",str);                                                          
    Sleep(5000);/*这里等待5秒,告诉你程序运行到什么地方*/                       
    scanf("%s",str1);/*这两句无需你再输入,是对stdin流再扫描*/                  
    scanf("%s",str2);/*这两句无需你再输入,是对stdin流再扫描*/                  
    printf("%s\n",str1);                                                         
    printf("%s\n",str2);                                                         
    return 0;                                                                     
}     

由此可知残留的信息是保存在stdin输入流里面,而不是缓冲区里面 

三,数据的存储 引言

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main() {
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0;i < 12;i++) {
		arr[i] = 0;
		printf("hehe\n");
		return 0;
	}
	return 0;
}

我们这个代码其实是一个错误的代码,有数组溢出的风险,但是我们分别debug和release去运行
debug的

release反而相反

存储
C99(1999年推出的C语言第三代)里面有long long为8个字节
类型
long为4个字节或者8个字节>=int(在X86平台下为4字节,在X64平台下为4字节)
short为2字节
类型的意义:1,开辟内存空间的大小     2,看待内存空间的大小

整形家族
字符型本质就是ASCII码,所以划分到整形

char有三种类型,char!=signed char(不一定)这个取决于编译器,可能是signed char或者unsigned char
int有两种类型,int=signed int

signed和unsigned的意义
在现实生活中,如果没有负数(如:身高,体重,…),有负数(温度,体温…)
有符号的正数范围会减小,无符号的正数的分为会变大

其他类型
自定义类型:数组,枚举,联合体,结构体
指针类型:空类型void*
void作为形参的时候,只是起说明作用

四,整数存储

进制的快速判断为多少的技巧

我看这个图不难的出里面其中的规律,每往前面前进对应的数字的次方都是+1,然后最后利用数字与这些数字相乘即可 

进制的三种类型

三种类型:1,原码     2,补码     3,反码
正数:三种类型都是相同的
负数:反码:除符号位不变,其余的按位取反
           补码:在反码的基础上加上1
内存其实存储的是二进制,但是在显示器上面显示的为16进制,并且存储的为二进制的补码
为什么要用补码而不是原码呢?
我们以1-1为例子

根据上面这个图,应该很快就可以理解了

大小端

int a = 20
0x 11 22 33 44
int b = -10
0x 55 66 77 88

大端:高位放高端            小端:地位放高端
总:大端正常,小端反常
很多编译器都是以小端的形式存储的
 

五,小数存储


1E10为1.0*10^10

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main() {
	int n = 9;
	float* pfloat = (float*)&n;
	printf("%d\n", n);
	printf("%f\n", *pfloat);
	*pfloat = 9.0;
	printf("%d\n", n);
	printf("%f\n", *pfloat);
}

当你看到这个答案,肯定会以为是9,9.000000,9,9.000000
当然答案并不是这个
 答案是这个,为什么呢?接下来,小数的存储会给你答案

浮点数的存储规则:
根据IEEE规定,任意一个二进制浮点数V可以表示下面的形式
V=(-1)^s*M*2^E
(-1)^s为符号位     s=0为正数,s=1为正数
M为有效数字 >=1     <2
2^E表示指数

这里有两个例子,首先二进制表示这个浮点数,小数点的左边跟正数一模一样,小数点的右边也跟正数差不多,只不过为负的次方

为什么有的数字不精确,这就可以得出答案了,因为后面就是2^-1,2^-2……这样没办法对于一些数字的精确

计算机是对于ME有相关规定的

根据IEEE规定,在计算机内部保存M的时候,默认这个M为1的,如果只有一个M的话可以省掉不屑,如保存1.01的时候,可以写成.01
目的:提高精度,舍掉1存1,则从23位数跳到了24位数

E
unsigned int类型
但E也有可能为-1
0.5---0.1---1.0*2^-1---(-1)^0*1.0*2^-1
由于出现了-1,这个规则就需要完善
则就出现了中间值这个概念(以0.5为例子)
(浮点类型为1023,整形类型为127)
float---E(真实值)+127(中间值)---126---存储
double---E(真实值)+1023(中间值)---1022---存储

例子
5.5---(-1)^0*1.011*2^2
E1=E+127=129---存储

浮点数的拿出
E不全为0或者不全为1时
E-127,同时M前面加1,5.5为例子
 这个就是在011前面加1.,然后后面这个次方2就是减去127即可

E全为0,直接为1-127或者1-1023就是真实值,表示无穷小
E全为1,这里M的有效数字为0,表示无穷大
E0.000……表示+-0无限接近0的数字


总结

1,debug和release
一个是运用到代码开发,一个运用到发布
debug是用于改进代码,会爆出相应的错误,但是包含的库文件就会更加庞大
release是用于优化代码,会自动优化代码,包含的库文件文件会比较小,但是不会报错,不适用代码开发

2,scanf()
遇到空格等字符会进行停止扫面,剩下的部分在stdin流里面,而不是键盘输入流

3,整数的存储
整形的家族是包括char类型的,而且要知道无符号和有符号的意义
整形的存储有三个形式,原码,反码,补码
计算机存储的补码,原因是可以便于进行计算,计算之后直接就是答案了

4,浮点数的存储
(-1)^s*M*2^E
首先我们利用二进制,小数点左边就是整数一样的二进制形式,右边就是次方为相反数,这个就是小数不可以精确的原因了
M规则:可以把第一个1省略掉,这样就可以从23位到24位,扩大范围
S规则:由于位unsigned int类型,所以就有了中间值这个概念,float:127    double:1023
浮点数存储位第一位:s值,后8位:表示M,剩下的就是小数点后面的数字了,然后再后面补0就好了
 

相关文章:

  • Docker高级篇
  • 无限使用,自动解锁全部版!
  • 基于角色访问控制的UML 表示04
  • 多模态对齐损失设计全解析:CLIP模型实现图文语义空间统一的原理详解与实战指南
  • 基于CANopen协议的同步控制和PDO消息传输
  • 考研操作系统----IO
  • 【学术投稿-第五届应用数学、建模与智能计算国际学术会议】CSS伪类选择器深度解析:分类、应用与技巧
  • C++拷贝构造函数初级解析:设计要点、调用机制与性能优化实践
  • 【NLP】文本预处理
  • ArrayList
  • 【第13章:自监督学习与少样本学习—13.3 自监督学习与少样本学习在图像识别、语言理解等领域的应用探索】
  • 网络安全学习笔记之Internet基本知识
  • 服务器A到服务器B免密登录
  • 哈希动态规划dp_5
  • 《探秘Windows 11驱动开发:从入门到实战》
  • FreeRTOS第1篇:FreeRTOS的“内核心脏”——任务管理机制
  • 2025 N1CTF crypto 复现
  • 微信小程序image组件mode属性详解
  • HTML之JavaScript对象
  • 【JVM系列】谈一谈JVM调优
  • 商务部再回应中美经贸高层会谈:美方要拿出诚意、拿出行动
  • 金融监管总局:力争实现全国普惠型小微企业贷款增速不低于各项贷款增速
  • 马克思主义理论研究教学名师系列访谈|鲍金:给予学生一碗水、自己就要有一桶水
  • 巴基斯坦军方:印度导弹袭击已造成至少3人死亡
  • 41年轮回,从洛杉矶奔向洛杉矶,李宁故地重游再出发
  • 中国医药科技出版社回应发布“男性患子宫肌瘤”论文:正在核查