学C的第二十二天【深度剖析数据在内存中的存储:1. 数据类型介绍;2. 整型在内存中的存储】

news2025/4/28 8:35:34

=========================================================================

相关代码gitee自取:C语言学习日记: 加油努力 (gitee.com)

=========================================================================

接上期:学C的第二十一天【初阶测评讲解:1. 计算递归了几次;2. 判断 do while 循环执行了几次;3. 求输入的两个数的最小公倍数;4. 将一句话的单词进行倒置,标点不倒置;补充知识点】_高高的胖子的博客-CSDN博客

=========================================================================

               

1. 数据类型介绍

(1). 基本的内置类型(C语言自带类型):

           

char        --        字符数据类型        --        1字节

            

short        --        短整型        --        2字节

            

int        --        型        --        4字节

            

long        --        长整型        --        4字节 或 8字节

sizeof(long)        >=        sizeof(int)

            

long long        --        更长的整型        --        8字节

            

float        --        单精度浮点数        --        4字节

            

double        --        双精度浮点数        --        8字节

           

                       

类型的意义:

           

1. 使用这个类型开辟内存空间的大小(大小决定了使用范围

                   

2. C语言规定了:sizeof(long) >= sizeof(int),所以long的大小可以是4字节8字节

              

3. 把整型分为短整型、整型和长整型的原因:有些整型数据可能比较小,使用short就够了,如:年龄。short的范围:-32768 ~ 32767

                        

4. 对于整型类型,还分为 有符号(signed) 无符号(unsigned)

               

               

(2). 类型的基本归类:

              

整型类型:(只有整型分有符号和无符号)

char

unsigned char

signed char

(字符存储时,存储的是ASCII码值,是整型,所以归类时把char放在整型类型中)

(直接写成 charsigned char 还是 unsigned char不确定的,取决于编译器)

         

short

unsigned short [int]

signed short [int]        ==        short [int]

(    [int]通常会省略掉    )

         

int

unsigned int

signed int        ==        int

             

long 

unsigned long [int]

signed long [int]        ==        long [int]

(    [int]通常会省略掉    )

          

long long 

unsigned long long [int]

signed long long [int]        ==        long long [int]

(    [int]通常会省略掉    )

                  

signed:二进制位的最高位符号位其它位都是 数值位

unsigned:二进制位的最高位也是 数值位,即所有位都是 数值位

             

例如(其它整型类型以此类推):

             

signed char 范围是:-128~127补码:10000000无法转换为原码,被直接当成-128

               

unsigned char 范围是:0~255,8位全是数值位,无负数

            

               

浮点数类型:

float

            

double

          

long double

           

构造类型(自定义类型):

            

数组类型:

           

数组的元素个数数组的类型 发生变化时,数组类型就不一样了:)

int arr1[10];        类型是        int [10]

int arr2[5];        类型是        int [5]

char arr3[5];        类型是        char [5]

(这是三个不同的数组类型)

          

           

结构体类型 struct

       

枚举类型 enum

      

联合类型 union

           

               

指针类型:

int* pi;

           

char* pc;

             

float* pf;

           

void* pv;

               

             

空类型:

void 表示 空类型无类型):通常应用于函数的返回类型函数的参数指针类型

                          


                             

2. 整型在内存中的存储

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

             

而开辟空间后,数据在所开辟内存中是如何存储的呢?

               

                

(1). 整数用二进制表示的三种表示形式:原码、反码、补码

             

                 

原码:

正数:直接数值按照正负数的形式翻译二进制得到原码

              

负数:直接数值按照正负数的形式翻译二进制得到原码

或者

反码按位取反得到原码

再或者

补码按位取反再+1得到原码

             

反码:

正数:原码、反码、补码 都相同

          

负数:原码符号位不变,将其它位依次按位取反得到反码

或者

补码-1得到反码

          

补码:

正数:原码、反码、补码 都相同

负数:反码+1得到补码

             

              

(2). 符号位 和 数值位(整数)

             

上面三种表示形式都有 符号位 和 数值位 两部分:

               

符号位:

二进制最高位的一位叫做符号位

符号位 用 0 表示 “”;

符号位 用 1 表示 “”。 

           

数值位:

除了符号位,其它位都是数值位

对于正数原码反码、补码 相同

对于负数三种表示方法各不相同(参考上面)

          

(演示代码:)

#include <stdio.h>
int main() 
{
	int num = 10;//创建一个叫num的整型变量,这时num向内存申请4个字节来存放数据
	// 4个字节 - 32比特位
	//00000000000000000000000000001010 -- 原码
	//00000000000000000000000000001010 -- 反码
	//00000000000000000000000000001010 -- 补码

	int num2 = -10;
	//10000000000000000000000000001010 -- 原码
	//11111111111111111111111111110101 -- 反码
	//11111111111111111111111111110110 -- 补码



	return 0;
}

             

                  

对于整型来说:数据存放在内存中其实存放的是补码

           

计算机系统中,数值一律用 补码表示存储

原因在于:使用补码,可以符号位数值位统一处理把符号位也看成数值位来计算

同时,加法减法也可以统一处理CPU只有加法器),

此为,补码原码相互转换,其运算过程是相同的

原码转换为补码按位取反再+1补码转换为原码也可以按位取反再+1),

不需要额外的硬件电路

               

只有加法器计算减法时1 - 1 --> 1 + (-1)

假设计算用的是原码,算出来的是 -2,是错误

而用补码进行计算后,再用原码表示,结果则是

        

(为什么会倒着存储呢?)

             

               

(3). 大小端介绍

                  

字节序:

字节单位讨论存储顺序大端字节序存储 / 小端字节序存储

                  

低位 / 高位:

十进制:数字123,1是百位,2是十位,3是个位。这里的1就是高位,3就是低位。

十六进制0x 11 22 33 44,这里 11 就是高位44就是低位

                  

大端字节序存储:

大端(存储)模式:指数据的低位字节内容保存在内存的高地址中,而数据的高位字节内容,保存在内存的低地址中;

低位高地址高位低地址

            

小端字节序存储:

小段(存储)模式:指数据的低位字节内容保存在内存的低地址中,而数据的高位字节内容,保存在内存的高地址中;

低位低地址高位高地址

            

为什么有大端和小段:

一个数据只要超过一个字节,在内存中存储的时候就必然涉及到顺序的问题,所以要有大端小端存储模式对该数据进行排序

                

为什么会有大小端模式之分,是因为在计算机系统中,我们是以字节为单位的,每个地址单元对应一个字节一个字节8bit 。但是在C语言中除了 8bitchar 之外,还有 16bit short 类型,32位 long 类型(具体要看编译器),另外,对于位数大于8位的处理器,例如 16位 或者 32位处理器,由于寄存器宽度大于一个字节,那么就存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式小端存储模式 。

              

例如:一个 16bit short 类型 x ,在内存中的地址0x0010x 的值0x1122,那么 0x11 高字节0x22低字节。对于大端模式,就将 0x11 放在低地址中,即地址 0x0010 中, 0x22 放在高地址中,即地址 0x0011 中。小端模式相反

          

我们常用的 x86 结构小端模式,所以上面的图数据会“倒着放”低位字节放在了低地址高位字节放在了高地址。而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择为大端模式还是小端模式。

               

             

(4). 写个程序判断大小端:

               

思路:

变量a存放在内存中的十六进制数为:01 00 00 00(小端存储),地址第一位是1

如果是大端存储:则应该是:00 00 00 01,地址第一位是0

可以把 a 的地址取出第一位,如果

第一位地址 == 1,说明是小端存储

第一位地址 == 0,说明是大端存储

         

取出 int类型a 的 地址 第一位方法:

*(char*)&a

int* 强制转换为 char*,再解引用,即可取出一位地址的内容

             

实现代码:

#include <stdio.h>
int check_sys()
{
	int a = 1;
	//要大于一个字节的数据,才有顺序可言

	判断大小端
	//if (*(char*)&a == 1)
	//	//把int*强制转换a的地址为char*再解引用,判断地址第一位的内容
	//{
	//	return 1;
	//}
	//else
	//{
	//	return 0;
	//}

	//可以直接写成
	return *(char*)&a;
}

int main() 
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}

	return 0;
}

            

                  

(5). 练习:(重点在注释)

             

1. 区别 unsigned 和 signed :

//练习:1.区别 unsigned 和 signed
#include <stdio.h>
int main() 
{
	char a = -1; //char 在 VS中 默认是 signed char
	//10000000000000000000000000000001 -- 原码
	//11111111111111111111111111111110 -- 反码
	//11111111111111111111111111111111 -- 补码
	//	-1是整数,存进char类型中会发生截断
	//				11111111	--	  补码,截断获取最低8位
	// 最高位 是 符号位

	signed char b = -1;
	//和 char a 相同

	unsigned char c = -1;
	//				11111111	--	  补码,截断获取最低8位
	// 最高位 是 数值位

	printf("a=%d,b=%d,c=%d", a, b, c);
	//%d - 十进制形式打印有符号整型数据,
	//这里会发生 整型提升
	//	11111111	--	  补码,截断获取最低8位
	// 
	//	整型提升,有符号位按符号位补满,补满后:
	//11111111111111111111111111111111 -- 整型提升后补码
	//11111111111111111111111111111110 -- 反码
	//10000000000000000000000000000001 -- 原码
	//	
	//	整型提升,无符号位高位补0,补满后:
	//00000000000000000000000011111111 -- 整型提升后补码
	//		整数原码、反码、补码相同

	return 0;
}

                

            

2. 使用 %u 打印 有符号整型:

            

(补充:%u -- 十进制形式打印无符号整型

               

(1). 打印 -128

//练习:2.使用 %u 打印 有符号整型:
#include <stdio.h>
int main() 
{
	char a = -128;
	//10000000000000000000000010000000 -- 原码
	//11111111111111111111111101111111 -- 反码
	//11111111111111111111111110000000 -- 补码
	//				截断后:
	//			10000000	-- 截断后补码

	printf("%u\n", a);
	// %u -- 十进制形式打印无符号的整型
	// 对 char 变量 打印 整型数字,进行整型提升
	// char类型 有符号位,按符号位补满:
	//11111111111111111111111110000000 -- 补满后的补码
	//因为是以 无符号整数 打印,所以 原码、反码、补码 相同
	// 那么这个数就很大了

	return 0;
}

                       

(2). 打印 128

//练习:3.使用 %u 打印 有符号整型:
#include <stdio.h>
int main()
{
	// -128 改成 128
	char a = 128;
	//00000000000000000000000010000000 -- 原码
	//11111111111111111111111101111111 -- 反码
	//11111111111111111111111110000000 -- 补码
	//				截断后:
	//			10000000	-- 截断后补码
	//	跟-128是一样的,
	//只是原码的符号位不一样,但截断后都是10000000

	printf("%u\n", a);
	// %u -- 十进制形式打印无符号的整型
	// 对 char 变量 打印 整型数字,进行整型提升
	// char类型 有符号位,按符号位补满:
	//11111111111111111111111110000000 -- 补满后的补码
	//因为是以 无符号整数 打印,所以 原码、反码、补码 相同
	// 那么这个数就很大了

	return 0;
}

                

               

3. 用%d打印:有符号整型 + 无符号整型

//练习:3. 用%d打印:有符号整型 + 无符号整型
#include <stdio.h>
int main() 
{
	//有符号整型:
	int i = -20;
	//10000000000000000000000000010100 -- 原码
	//11111111111111111111111111101011 -- 反码
	//11111111111111111111111111101100 -- 补码

	//无符号整型:
	unsigned int j = 10;
	//00000000000000000000000000001010 -- 原码
	//			原码、反码、补码 相同

	printf("%d\n", i + j);
	// i的补码 和 j的补码 相加
	//11111111111111111111111111101100 -- i的补码
	//				+
	//00000000000000000000000000001010 -- j的补码
	//				=
	//11111111111111111111111111110110 -- 两补码相加后的补码
	//该补码再通过%d打印有符号数,最高位是符号位,知道补码,要计算得到原码
	//11111111111111111111111111110101 -- 反码
	//		反码 符号位 不变,其它位 按位取反
	//10000000000000000000000000001010 -- 原码 -》 -10

	return 0;
}

                

               

4. 使用无符号整数(无负数)进行自减循环

//使用无符号整数(无负数)进行自减循环
#include <stdio.h>
#include <windows.h>

int main() 
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
		Sleep(1000);
		//单位是毫秒,休眠1秒再继续下个语句
	}

	return 0;
}

               

                  

5. 字符数组存储整型数字:

//字符数组存储整型数字:
#include <stdio.h>
#include <string.h>
int main() 
{
	char a[1000];
	//char类型数组,整型数字只能存储0~-128

	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;//-1,-2......
	}
	//-1,-2,-3...-128,127,126,...3,2,1,0 -- 存一轮:256个元素
	//-1,-2,-3...-128,127,126,...3,2,1,0 -- 存一轮:256个元素
	//。。。。。

	printf("%d", strlen(a));
	//strlen 是求字符串长度的,
	//统计的是 \0 之前出现的字符的个数
	// \0 的ASCII码值是 0,找到0就停止计算

	return 0;
}

              

               

6. unsigned char 取值范围:

//unsigned char 取值范围:
#include <stdio.h>

unsigned char i = 0;//全局变量
//unsigned char 的整型取值范围是:0~255

int main() 
{
	// 255 再 +1 又变成 0
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

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

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

相关文章

day39_servlet

今日内容 零、复习昨日 一、接收请求 二、处理响应 三、综合案例 零、复习昨日 见晨考 一、接收请求 浏览器发出请求,经过web.xml映射匹配,找到Servlet对应的方法(doGet/doPost),接收请求数据,可以接收请求中的请求行,请求头,请求正文&#xff0c;具体流程如下 浏览器发出请求 …

OpenAI ChatGPT API + FaskAPI SSE Stream 流式周转技术 以及前端Fetch 流式请求获取案例

先填坑&#xff0c;一贯习惯 nginx如果要支持SSE&#xff0c;要调整一些参数 conf配置文件&#xff0c;AI给的&#xff0c;具体自己没搭&#xff0c;应该是正确的 nginx worker_processes 1;events {worker_connections 1024; }http {include mime.types;default_typ…

Ubuntu下编译运行MicroPython Unix版本

文章目录 github拉取源码更新模块编译运行 github拉取源码 到Github(https://github.com/micropython/micropython)上下载源码 终端输入&#xff0c;如果提示识别不到gh命令&#xff0c;就sudo apt-get install gc安装一下。 再根据提示在终端里登录自己的github账号。 再次…

Hystrix 服务熔断

书籍,人,借阅服务之间相互调用, 高度耦合, 一旦一个服务故障, 其他服务会雪崩, 和多米诺骨牌一样 Hystrix 熔断器, 保险丝 服务降级 提供补救措施发给请求者, 服务可用, 能力下降了 borrow-service 导入依赖 <dependency><groupId>org.springframework.cloud&l…

linux kernel pwn 常用结构体

tty 设备结构体 tty 设备在 /dev 下的一个伪终端设备 ptmx 。 tty_struct&#xff08;kmalloc-1k | GFP_KERNEL_ACCOUNT&#xff09; tty_struct 定义如下 。 /* tty magic number */ #define TTY_MAGIC 0x5401struct tty_struct {int magic;...const struct tty…

python学习-基础知识总结

&#xff08;一&#xff09;基础语法 1.1、注释 程序添加注释&#xff0c;可以用来解释程序某些部分的作用和功能&#xff0c;提高程序的可读性&#xff0c;注释有两种形式&#xff1a; 单行注释&#xff1a;#多行注释&#xff1a;单引号&#xff08;注释内容&#xff09;或双…

【剑指offer】数据结构——字符串

目录 数据结构——字符串直接解【剑指offer】05. 替换空格【剑指offer】17. 打印从1到最大的n位数【剑指offer】20. 表示数值的字符串【剑指offer】37. 序列化二叉树【剑指offer】50. 第一个只出现一次的字符【剑指offer】58. 翻转单词顺序【剑指offer】58.2 左旋转字符串【剑指…

C++多态 万字详解

在经历两个多月的备赛后&#xff0c;最终5.21结果出来后自己也比较满意&#xff0c;以一个省三收尾&#xff08;算法类的&#xff09;。 期间每天偶尔学学新知识&#xff0c;然后主要做题&#xff0c;博客也落下了不少&#xff0c;现在开始继续补&#xff08;可能会些许生疏&a…

【剑指offer】数据结构——数组

目录 数据结构——数组直接解【剑指offer】03.数组中重复的数字排序法集合法原地置换 【剑指offer】04. 二维数组中的查找【剑指offer】29. 顺时针打印矩阵【剑指offer】39. 数组中出现次数超过一半的数字【剑指offer】40. 最小的k个数【剑指offer】45. 把数组排成最小的数【剑…

C++ 实现命令行画心形代码,有多个爱心代码,简单可调数据和字符,可装X,也可用于浪漫的表白,可实现跳动、保存等功能

绘制一个简易爱心 #include <stdio.h> #include <Windows.h>int main() {for (float y 1.5f; y > -1.5f; y - 0.1f){for (float x -1.5f; x < 1.5f; x 0.05f){float z x * x y * y - 1;float f z * z * z - x * x * y * y * y;putchar(f < 0.0f ?…

一文带你了解MySQL之基于规则的优化

前言&#xff1a; 大家别忘了MySQL本质上是一个软件&#xff0c;MySQL的并不能要求使用这个软件的人人都是数据库的高手&#xff0c;就像我写这篇文章的时候并不能要求各位在学之前就会了里边的知识。也就是说我们无法避免某些小伙伴写一些执行起来十分耗费性能的语句。即使是…

【youcans 的图像处理学习课】22. Haar 级联分类器

专栏地址&#xff1a;『youcans 的图像处理学习课』 文章目录&#xff1a;『youcans 的图像处理学习课 - 总目录』 【youcans 的图像处理学习课】22. Haar 级联分类器 3. Haar 特征及其加速计算3.1 Haar 特征3.2 Haar 特征值的计算3.3 积分图像3.4 基于积分图像加速计算 Haar 特…

MATLAB 如何以海森频率格子格纸的形式绘制频率分布曲线?

思路&#xff1a;将水文频率在海森格纸上对应的位置算出来&#xff0c;通过更改坐标轴标签制作海森频率格纸 先放参考链接&#xff1a; norminv 如何利用matlab在海森几率格纸上绘制图形 clc clear close all%% 随机生成径流系列&#xff0c;并计算对应频率 q randi(1000,…

Thymeleaf语法和流程控制,简单传值,each循环,if判断,switch.case使用

Thymeleaf怎么调用静态资源的看我之前发过的文章 这个首先在controller创建一个book的类&#xff0c;book的一些属性自己定义记得getsetyix Controller RequestMapping("/book") public class BookController {RequestMapping("/query")public String qu…

建立基于Open vSwitch的GRE隧道

建立基于Open vSwitch的GRE隧道 1. 环境的准备 图6-1 连接拓扑图 如图6-1所示为两台虚拟机连接拓扑图&#xff0c;两台虚拟机ens33网卡&#xff0c;通过虚拟交换机连接在一起&#xff0c;地址网段为30.0.0.0/24。在Docker主机ens33&#xff0c;IP地址为30.0.0.10/24&#xff…

从0到1接入钉钉消息通知

前段时间给项目接入监控告警&#xff0c;消息通知渠道选了钉钉。预算的原因内部办公刚从飞书转回钉钉&#xff0c;飞书消息通知之前就有一套了&#xff0c;测试钉钉从应用授权到消息测试花了不少时间。这里记录下从钉钉开放平台权限申请到消息接收全流程&#xff0c;给后面有同…

SAP-MM-采购申请字段解析

采购申请抬头以及行项目字段解析 1、采购申请类型&#xff1a; 对PR进行分类&#xff1b; 控制PR行项目的编号间隔&#xff1b; 控制PR编号范围&#xff0c;以及是否内/外部给号&#xff1b; 控制PR的屏幕选择格式&#xff1b; 控制PR是否允许凭证抬头审批&#xff0c;如果允…

mybatis-plus实现逻辑删除(详细!)

文章目录 什么是逻辑删除&#xff1f;为什么用到逻辑删除&#xff1f;在springboot使用Mybatis-Plus提供的逻辑删除1、在application.yml配置2、 实体类字段上加上TableLogic注解演示 什么是逻辑删除&#xff1f; 逻辑删除的本质是修改操作&#xff0c;并不是真正的删除&#…

2023/5/28周报

目录 摘要 论文阅读 1、标题和现存问题 2、使用GNN进行文本分类 3、INDUCT-GCN 4、实验准备 5、实验结果 深度学习 1、时空图的种类 2、图在环境中的应用 3、STGNN 总结 摘要 本周在论文阅读上&#xff0c;阅读了一篇InducT-GCN:归纳图卷积文本分类网络的论文。基…

AWVS使用手册

目录 AWVS基本操作 AWVS工具介绍 AWVS界面介绍 AWVS主要操作区域简介 AWVS的功能及特点的功能及特点 AWVS的菜单栏&#xff0c;工具栏简介 AWVS基本功能介绍 AWVS的蜘蛛爬虫功能 AWVS目标目标探测工具 AWVS的子域名探测工具 AWVS的的HTTP嗅探工具 AWVS的的HTTP模糊…