C语言进阶--数据的存储

1.数据类型介绍

内置类型

char  //字符数据类型  1字节
short  //短整型      2字节
int  //整型          4字节
long  //长整型       4/8字节
long long  //更长的整型  8字节   (C99中引入的)
float  //单精度浮点数    4字节
double  //双精度浮点数   8字节sizeof(long) >= sizeof(int)
4(32位平台)/8(64位平台)  >=  4   字节

类型的意义

  • 使用这个类型开辟内存空间的大小(大小决定使用范围)
  • 如何看待内存空间的视角

1.1类型的基本归类

整型家族

char    (字符的本质是ASCII码值,属于整型,所以划分到整型家族)  (char 类型 到底是signed char 还是unsigned char ,在C语言标准中是未定义的,取决于编译器的实现) —— char 比较特殊unsigned charsigned charshortunsigned short [int]signed short [int]int     (int a; ————> 这里的int类型默认指的是signed int) unsigned intsigned intlongunsigned long [int]signed long [int]long longunsigned long long [int] signed long long [int]

生活中有些数据是没有负数的,比如身高,体重,长度等。 ——> unsigned

但有些数据是有负数的,比如温度。——> signed

浮点型家族

float
double

只要是表示小数就可以使用浮点型。

float的精度低,存储的数值范围较小;double的精度高,存储的数值范围更大。

构造类型(自定义类型:我们可以自己创建出新的类型)

数组类型
结构体类型 struct
枚举类型 enum
联合类型 union    
//数组类型
int arr1[5]; //数组类型:int [5]
int arr2[8]; //数组类型:int [8]
char arr3[5]; //数组类型:char [5]

指针类型

int* pi;
char* pc;
float* pf;
void* pv;

空类型

void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型    
void test(void) //第一个void 表示函数没有返回值;第二个void 表示函数不需要传任何参数
{}

2.整型在内存中的存储

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

//数值有不同的表示形式,2进制,8进制,10进制,16进制
//eg:21
//0b10101 —— 025 —— 21 —— 0x15

2.1原码、反码、补码

整数的2进制表示也有3种表示形式:原码、反码、补码。

1.正的整数,原码、反码、补码相同。

2.负的整数,原码、反码、补码是需要计算的。

原码(直接通过正负的形式写出的二进制序列)

反码(原码的符号位不变,其它位按位取反)

补码(反码+1)

int main()
{int a = 20;//00000000 00000000 00000000 00010100 - 原码(二进制)//0x00 00 00 14 - 原码、反码、补码(十六进制)//00000000 00000000 00000000 00010100 - 反码(二进制)//00000000 00000000 00000000 00010100 - 补码(二进制)int b = -10;//10000000 00000000 00000000 00001010 - 原码(二进制)//0x80 00 00 0a - 原码(十六进制)//11111111 11111111 11111111 11110101 - 反码(二进制)//0xff ff ff f5 - 反码(十六进制)//11111111 11111111 11111111 11110110 - 补码(二进制)   //0xff ff ff f6 - 补码(十六进制)return 0;
}

在这里插入图片描述
整数在内存中存放的是补码的二进制序列。

为什么呢?

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

2.2大小端介绍

在这里插入图片描述
大端【字节序】存储:把一个数据的高位字节序的内容放在低地址处,把低位字节序的内容放在高地址处。

小端【字节序】存储:把一个数据的高位字节序的内容放在高地址处,把低位字节序的内容放在低地址处。

我们常用的X86结构是小端模式,而KEIL C51为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择大端模式还是小端模式。

//判断大小端
#include <stdio.h>int main()
{int a = 1;if (*(char*)&a == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}
//判断大小端(封装成函数)
#include <stdio.h>
int check_sys()
{int a = 1;if (*(char*)&a == 1){return 1;}else{return 0;}
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}
//判断大小端(封装成函数,简洁版)
#include <stdio.h>
int check_sys()
{int a = 1;return *(char*)&a;
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}

3.浮点型在内存中的存储

常见的浮点数:

3.14159

1E10(1.0*e的10次方,科学计数法)

浮点数家族:float、double、long double(C99中引入)类型。

浮点数表示的范围:float.h中定义。

整数表示的范围:limits.h中定义。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1浮点数存储序列

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

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

  • (-1)^S【-1的S次方】表示符号位。当S=0,V为正数;当S=1,V为负数。
  • M表示有效数字。大于等于1,小于2.
  • 2^E【2的E次方】表示指数位。

IEEE 754规定:

对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的32位是有效数字M。

在这里插入图片描述
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位是有效数字M。

在这里插入图片描述
IEEE 754对有效数字M和指数E,还有一些特别的规定:

前面说过,1<=M<2,也就是说,M可以写成1.xxxx的形式,其中xxxx表示小数部分。

IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxx部分。比如保存1.01时,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的:节省1位有效数字。

至于指数E,情况比较复杂。

首先,E为一个无符号整数(unsigned int),这意味着,如果E为8位,它的取值范围是0-255;如果E为11位,它的取值范围是0-2047。但是,我们知道,科学计数法中的E是可以出现负数的。所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数。对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

int main()
{float f = 5.5f;//101.1 - 二进制//1.011*2^2 - 科学计数法//S=0,M=1.011,E=2(存储时+中间值127=129)//0 10000001 011(后面不足23bit直接补0)00000000000000000000//01000000101100000000000000000000//0100 0000 1011 0000 0000 0000 0000 0000(写出16进制)//0x40 b0 00 00return 0;
}

在这里插入图片描述
然后,指数E从内存这种取出还可以分成三种情况:

E不全为0或不全为1

这时,浮点数就采用下面的规则表示:即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

比如:

0 10000001 01100000000000000000000
(-1)^0 * 1.01100000000000000000000 * 2^2129-127=2

E全为0

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

E全为1

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

作业1:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。

//输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。#include <stdio.h>void move_odd_even(int arr[], int sz)
{int left = 0;int right = sz - 1;while (left < right){//从左向右找一个偶数,遇到奇数停下来while ((left < right)&& (arr[left] % 2 == 1)) //可能存在越界,加上条件(left < right){left++;}//从右向左找一个奇数,遇到偶数停下来while ((left < right)&& (arr[right] % 2 == 0)){right--;}//交换奇数和偶数if (left < right){int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;left++;right--;}}
}
int main()
{int arr[10] = {0};//输入int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){//scanf("%d", &arr[i]); //等价于下面代码scanf("%d", arr+i);}//调整move_odd_even(arr, sz);//输出for (i = 0; i < sz; i++){printf("%d ", arr[i]); }return 0;
}

作业2:有序序列合并

#include <stdio.h>
int main()
{int n = 0;int m = 0;scanf("%d %d", &n, &m);int arr1[n]; //C99支持的变长数组int arr2[m];//输入n个整数int i = 0;for (i = 0; i < n; i++){scanf("%d", &arr1[i]);}//输入m个整数for (i = 0; i < m; i++){scanf("%d", &arr2[i]);}//合并打印int j = 0; //n数组下标int k = 0; //m数组下标while (j<n && k<m){if (arr1[j] < arr2[k]){printf("%d ", arr1[j]);j++;}else{printf("%d ", arr2[k]);k++;}}if (j<n){for (; j < n; j++){printf("%d ", arr1[j]);}}else //k<m{for (; k < m; k++){printf("%d ", arr2[k]);}}return 0;
}
//如果要存储在一个新数组里面
#include <stdio.h>
int main()
{int n = 0;int m = 0;scanf("%d %d", &n, &m);int arr1[n]; //C99支持的变长数组int arr2[m];int arr3[m+n];//输入n个整数int i = 0;for (i = 0; i < n; i++){scanf("%d", &arr1[i]);}//输入m个整数for (i = 0; i < m; i++){scanf("%d", &arr2[i]);}//合并打印int j = 0; //arr1数组下标int k = 0; //arr2数组下标int r = 0; //arr3数组下标while (j<n && k<m){if (arr1[j] < arr2[k]){arr3[r++] = arr1[j];//printf("%d ", arr1[j]);j++;}else{arr3[r++] = arr2[k];//printf("%d ", arr2[k]);k++;}}if (j<n){for (; j < n; j++){arr3[r++] = arr1[j];//printf("%d ", arr1[j]);}}else //k<m{for (; k < m; k++){arr3[r] = arr2[k];//printf("%d ", arr2[k]);}}//打印for (i = 0; i < m+n; i++){printf("%d ", arr3[i]);}return 0;
}

总结

今天就暂且更新至此吧,期待下周再会。如有错误还请不吝赐教。希望对您学习有所帮助,翻页前留下你的支持,以防下次失踪了嗷。

作者更新不易,免费关注别手软。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++学习细节回顾(汇总三)

一.多态概念 同样是动物叫的⼀个⾏为(函数)&#xff0c;传猫对象过去&#xff0c;就是”(>ω<)喵“&#xff0c;传狗对象过去&#xff0c;就是"汪汪"。 1.根据对象不同类型&#xff0c;调用不同函数&#xff0c;这就叫做运行时多态(动态多态) 2.编译时多态(静态…

SpringAI+MCPServer+MCPClient快速入门

SpringAI MCPServer MCPClient 快速入门编写大纲 源代码地址&#xff1a;https://download.csdn.net/download/user_admin_god/90926893 1. 介绍 本文通过使用免费的智普AI的glm-4-flash模型&#xff0c;设计并实现了一个智能问答系统。在该系统中&#xff0c;我们编写了一…

Linux `vi/vim` 编辑器深度解析与高阶应用指南

Linux `vi/vim` 编辑器深度解析与高阶应用指南 一、核心功能解析1. 模式系统2. 与主流编辑器对比二、核心操作体系1. 高效导航命令2. 文本操作矩阵三、高阶配置体系1. .vimrc 配置示例2. 插件管理系统四、企业级开发实践1. 代码编辑技巧2. 宏录制与批量处理五、可视化与多窗口1…

Java五种方法批量处理List元素全解

Java:如何优雅批量处理List中的每个元素 一、场景分析&#xff1a;为什么需要批量处理List&#xff1f;二、核心方法&#xff1a;五种实现方式对比2.1 普通for循环&#xff08;最直接的方式&#xff09;代码示例&#xff1a;优缺点&#xff1a; 2.2 Java 8 replaceAll&#xff…

【Elasticsearch】`_refresh`和`_flush`的区别

在Elasticsearch中&#xff0c;_refresh和_flush操作虽然看似都与“刷新”有关&#xff0c;但它们的功能和作用范围有显著区别&#xff1a; _refresh操作 - 目的&#xff1a;使索引操作&#xff08;如新增、更新、删除文档&#xff09;后的更改能够立即被搜索到。 - 工作原理…

Java核心数据类型:String深度解析(JDK 8+)

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 问题驱动&#xff1a;从用户注册场景说起 场景描述&#xff1a;开发一个用户注册功能时&#xff0c;需要处理用户名的校验、格式化和存储。你可能会遇到…

人员睡岗检测算法AI智能分析网关V4打造工业/安防/交通等多场景应用方案

一、引言​ 在工业生产、安防监控等多领域&#xff0c;众多岗位需员工长时间值守&#xff0c;如流水线工人、监控值班员等。但高强度工作易引发睡岗问题&#xff0c;导致生产效率下降&#xff0c;甚至造成安全事故与财产损失。传统人工巡检响应慢、成本高&#xff0c;难以满足…

自动生成提示技术突破:AUTOPROMPT重塑语言模型应用

AUTOPROMPT 预训练语言模型的显著成功促使人们研究这些模型在预训练期间学习了哪些类型的知识。将任务重新表述为填空题(例如,完形填空测试)是衡量此类知识的自然方法 但是,它的使用受到编写合适提示所需的手动工作和猜测的限制。为了解决这个问题,我们开发了 AUTOPROMP…

6个月Python学习计划 Day 7 - 复盘 + 测试日

第一周 Day 1 - Python 基础入门 & 开发环境搭建 Day 2 - 条件判断、用户输入、格式化输出 Day 3 - 循环语句 range 函数 Day 4 - 列表 & 元组基础 Day 5 - 字典&#xff08;dict&#xff09;与集合&#xff08;set&#xff09; Day 6 - 综合实战&#xff1a;学生信息…

Pycharm and Flask 的学习心得(9)

request对象&#xff1a; 1. request包含前端发送过来的所有请求数据 将from表单里的内容CV到request里面&#xff0c;可以添加if语句来做判断出请求类型后的操作 在网页上的表单上input的数据&#xff0c;后端如何获取呢&#xff1f; request对象获取前端发送来的数据 // …

设计模式-依赖倒转原则

依赖倒转原则 依赖倒转原则 (Dependency Inversion Principle, DIP) 是面向对象设计中 SOLID 原则的第五个原则。 它包含两条核心思想&#xff1a; 高层模块不应该依赖于低层模块。两者都应该依赖于抽象。 高层模块 (High-level modules): 通常包含复杂的业务逻辑和策略&…

AI赋能引爆短剧全球化风潮,腾讯云媒体处理助力短剧平台出海吸金

2023年&#xff0c;中国短剧市场以全平台8000万日投放、近500亿规模的爆发式增长震惊行业。紧凑的内容、爽快的剧情令国内观众迅速爱上了几分钟一集的微短剧。然而在平台内卷、监管收紧、巨头入场等因素的冲击下&#xff0c;不到两年时间&#xff0c;这条赛道就已陷入红海。但与…

开源第三方库发展现状

摘要&#xff1a;当前&#xff0c;开源第三方库生态正呈现爆发式增长趋势。GitHub 目前已托管超过 4.2 亿个代码仓库&#xff0c;远超早期统计的 1 亿规模&#xff0c;显示出开发者社区的活跃度持续攀升。同时&#xff0c;37 个主流包管理器所维护的开源组件数量可能已达到数千…

服务器开机自启动服务

前言&#xff1a; 将服务器中脚本开启自启动执行 步骤&#xff1a; 1.创建一个 systemd 服务文件: /etc/systemd/system/ 目录下创建一个新的服务文件。例如&#xff0c;命名为 myapp.service&#xff1a; sudo nano /etc/systemd/system/myapp.service2.编写 [Unit] Descri…

采用Bright Data+n8n+AI打造自动化新闻助手:每天5分钟实现内容日更

一、引言 在信息爆炸的时代&#xff0c;作为科技领域的内容创作者&#xff0c;我每天都要花费2-3小时手动收集行业新闻、撰写摘要并发布到各个社群。直到我发现Bright Datan8nAI这套"黄金组合"&#xff0c;才真正实现了从"人工搬运"到"智能自动化&qu…

ROS云课三分钟-3D性能测试supertuxkart和游戏推荐等-国际象棋

ROS云课三分钟-破壁篇GCompris-一小部分支持Edu应用列表-2025-CSDN博客 很多时候&#xff0c;有一种思维定势&#xff0c;将人锁住&#xff0c;人口就是囚。 口人囚~口加人等于囚-CSDN博客 如果突破&#xff0c;跳出问题&#xff0c;再看问题。 这门课程&#xff0c;或者这个平…

学习率及相关优化参数详解:驱动模型高效训练

一、引言 在模型微调的核心参数体系中&#xff0c;优化相关参数是决定训练效率与模型性能的关键变量。它们如同精密机械的齿轮&#xff0c;彼此联动、相互影响&#xff0c;共同调控着模型在参数空间中的搜索路径。本文将围绕学习率、训练轮数、批处理大小、梯度累积和学习率调…

golang 柯里化(Currying)

使用场景&#xff1a;参数在语义上属于不同组&#xff0c;Go 语法无法在单次调用中声明多组可变参数&#xff0c;通过柯里化可以实现分步接收参数。 有的参数是在不同时间段产生&#xff0c;使用Currying可以让函数记住&#xff08;缓存&#xff09;参数&#xff0c;避免应用代…

电脑革命家测试版:硬件检测,6MB 轻量无广告 清理垃圾 + 禁用系统更新

各位电脑小白和大神们&#xff0c;我跟你们说啊&#xff01;有个超牛的东西叫电脑革命家测试版&#xff0c;这是吾爱破解论坛的开发者搞出来的免费无广告系统工具集合&#xff0c;主打硬件检测和系统优化&#xff0c;就像是鲁大师这些软件的平替。下面我给你们唠唠它的核心功能…

R 语言科研绘图第 52 期 --- 网络图-分组

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…