C语言之整数_数据存储篇(1)

目录

数据类型

整形家族

浮点型家族

构造类型

指针类型

空类型

整形在内存中的存储(原反补)

NO1.

NO2. 

NO3. 

NO4. 

NO5. 

NO6.

大端小端字节序

NO.1

NO.2

NO.3 

NO.4

练习题

NO1.

NO2.

NO3.

NO4.

NO5.

NO6.

总结 


数据类型

 在初C语言中,我们已经学习过基本内置类型以及它们所占存储空间的大小。我们再回顾一下。

 每一个类型所占空间的大小都不一样,这么多丰富的类型,那它们存在的意义是什么呢?

类型的意义:

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

这样我们就会在合适的场景选择合适的数据类型。 

整形家族

char
      unsigned char
      signed char
short
      unsigned short [int]
      signed short [int]
int
      unsigned int
      signed int
long
      unsigned long [int]
      signed long [int]
long long
//关于long long我们酌情使用。
signed     有符号的
unsigned   无符号的

 为什么char字符会归为整形家族?

字符在内存中的存储的是字符的ASCII码值,ASCII码值是整形。

signed和unsigned 修饰的整形有什么区别吗?

 signed是有符号的;unsigned int 是无符号的。

int a;//== sined int a
signed int a;
unsigned int a;

我们平时在编译器上创建一个变量,相当于创建一个有符号的变量。

当然short   long   long long 均是创建变量相当于创建一个有符号signed 的变量。(除了char)

那char呢?

char是否是相当于signed char?C语言标准并没有规定,取决于编译器。

大部分编译器是,不排除小部分编译器是unsigned int

ASCII码表中规定的ASCII码值的范围是0~127(字符均是正数)。

只有小部分负数是可以存储在 signed char

浮点型家族

float
double

long double
//建议酌情使用

构造类型

//自定义类型
> 数组类型
> 结构体类型 struct
> 枚举类型 enum
> 联合类型 union

指针类型

int *pi;
char *pc;
float* pf;
void* pv;//无具体类型的指针

空类型

 

void test(void)
//第一个void 表示test函数不会返回任何值
//第二个void 表示test函数没有参数
{
	//
}
int main(void)//
int main(int argc,char* argv[],char* envp[])

整形在内存中的存储(原反补)

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

NO1.

那接下来我们来谈谈数据在所开辟内存中到底是如何存储的呢?

计算机能够处理的是二进制的数据。

整型和浮点型数据在内存中也是以二进制的形式进行存储的。

整型在内存中存储的是补码的二进制序列。

NO2. 

 整型的二进制表示形式是怎样的呢?

计算机中的整型有三种二进制表示:原码,反码,补码。

  • 分为有 有符号整数 和 无符号整数。
  • 无符号整数:原码,反码,补码相同。
  • 有符号整数:三种表示方法均有 符号位 和 数值位 两部分。
  • 正数:原码,反码,补码相同。
  • 负数:原码,反码,补码要进行计算的。
  • 符号位:0 表示正
  • 符号位:1 表示负
  • 数值位:正数的原,反,补码相同。
  • 数值位:负数的原,反,补表示方法各不同。

NO3. 

signed int 和 unsigned int? 

 在内存中,对于存储一个整数需要4个字节,也就是32个比特位。

一个整数写出二进制序列的时候,也就是32个比特位。

有符号整数:最高位就是符号位。符号位是1,则表示是负数。符号位是0,则表示是正数

无符号整数:没有符号位,所有位都是数值位。

同一个数无论是有符号整数,还是无符号整数的 数值均相同。

有符号整数的最高位符号位还是会参与运算。

 如下:

#include<stdio.h>
int main()
{
	int a = 10;//== signed int
	//0 0000000 00000000 00000000 00001010
	unsigned int b =10;
    //00000000 00000000 00000000 00001010
	return 0;
}

站在a的角度,第一个0就是符号位。

站在b的角度,第一个0就是数值位。

NO4. 

负整数的原反补怎样转化呢? 

 

NO5. 

进制间的转化?这里我们不专门去讲解,可以自己学一学。

对于整形来说,数据存放内存中其实存放的是补码。为什么呢?

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

NO6.

#include<stdio.h>
int main()
{
	int a = -10;//== signed int
	//1 0000000 00000000 00000000 00001010
	//1 1111111 11111111 11111111 11110101
	//1111 1111 1111 1111 1111 1111 1111 0110——补码
	//十六进制
	//0x ff ff ff f6
	unsigned int b =-10;
    //10000000 00000000 00000000 00001010
	return 0;
}

整形在内存中是以二进制的补码存储的,在编译器中为了观瞻,是以十六进制的方式去展示给我们,请问为什么是以十六进制倒叙放置的呢?那接下来我们就要介绍我们的大小端字节序存储。

大端小端字节序

关于内存中二进制/十六进制,单位 比特位和字节的转换,如下图。

NO.1

大端小端产生?

int a=0x11223344
//1 2 3
//百位 十位 各位
//高位      低位

根据字节存储来解释。

我们可以有无数中存储方式,只要按照存进去的方式,在需要使用时拿出来按照原来的顺序放置还原。怎么存都可以!

但是为了简便我们只采用了两种存储方式:

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

除了字符整型,都是这两种存储方式,char1个字节不需要顺序。

NO.2

什么是大端小端?

NO.3 

为什么有大端小端?

NO.4

笔试题:请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序?

 

根据上图就有如下代码:

#include<stdio.h>
int main()
{
	int a = 1;//
	char* p = (char*)&a;//强制转化
	if (*p == 0)
		printf("大端\n");
	if(*p == 1)
		printf("小端\n");
	return 0;
}
//用函数包装呢?
#include<stdio.h>
int check_sys(void)
{
	int a = 1;
	char* p =(char*) &a;//强制类型转化
	if (*p == 0)
		return 0;
	if (*p == 1)
		return 1;
}
int main()
{
	int ret = check_sys();
	if (ret == 0)
		printf("大端\n");
	if (ret == 1)
		printf("小端\n");
	return 0;
}

//简化
#include<stdio.h>
int check_sys()
{
	int a = 1;
	return *(char*)&a;
}
int main()
{
	int ret = check_sys();
	if (ret == 0)
		printf("大端\n");
	if (ret == 1)
		printf("小端\n");
	return 0;
}

练习题

//以下主要讲解的是char类型的signed 和unsigned 
//可以推广到short/long等等
%d 是十进制的形式打印有符号整数
%u 是十进制的形式打印无符号整数

NO1.

请问下面程序a,b,c分别是多少? 

1.
//输出什么?
#include <stdio.h>
int main()
{
  char a= -1;
  signed char b=-1;
  unsigned char c=-1;
  printf("a=%d,b=%d,c=%d",a,b,c);
  return 0;
}

#include <stdio.h>
int main()
{
	char a = -1;
	//有符号的 负数 char类型
	// 10000000 00000000 00000000 00000001原码
	// 11111111 11111111 11111111 11111110反码
	// 11111111 11111111 11111111 11111111补码
	//存储char  11111111补码
	signed char b = -1;
	//有符号的 负数  char类型同上
	//存储char  11111111补码
	unsigned char c = -1;
	//无符号的  负数  char类型
	//无符号——没有符号位的概念
	// 无符号整数一般放置正数,如果放置负数还是按照负数的原反补来计算
	// 10000000 00000000 00000000 00000001原码
	// 01111111 11111111 11111111 11111110反码
	// 01111111 11111111 11111111 11111111补码
	// 存储char 11111111补码
	//存储char  11111111
	printf("a=%d,b=%d,c=%d", a, b, c);
	//%d 是十进制的形式打印有符号整数
	// 即便没有符号,当作有符号去打印
	//整型提升
	// 有符号位提升符号位
	// 无符号位补0,提升0
	// 有符号ab
	//11111111 11111111 11111111 11111111补码
    //10000000 00000000 00000000 00000001原码
	//打印-1
	//b同理-1
	//无符号c
	//1111111
	//00000000 00000000 00000000 11111111补码原码反码
	//正数的原码反码补码相同
	//打印-c
	//225
	return 0;
}

NO2.

 请问下面三端程序分别输出什么?

2.
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
//
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
//
#include <stdio.h>
int main()
{
char a = 384;//128+256
printf("%u\n",a);
return 0;
}
//2.
#include <stdio.h>
int main()
{
	char a = -128;
	//有符号整型 char 负数
	//10000000 00000000 00000000 10000000原码
	//11111111 11111111 11111111 01111111反码
	//11111111 11111111 11111111 10000000补码
	//存储a char        10000000
	printf("%u\n", a);
	//%u 是十进制打印无符号整型
	//整型提升——变量的类型(有符号/无符号)
	//1111111 111111111 11111111 10000000补码
	// 打印——看(u/d)——(u_原反补相同/d_正原反补相同_负的计算)
	//%u把a看成无符号整数
	// 1就不是a的符号位了
	//打印
	//无符号整型原反补相同
	//4,294,967,168
	return 0;
}
//
#include <stdio.h>
int main()
{
	char a = 128;
	//原反补相同
	//00000000 00000000 00000000 10000000补码
	//存储     10000000
	printf("%u\n", a);
	//提升     11111111 11111111 11111111 10000000补码
	//打印——看成无符号的——原反补相同
	//所以还是同上
	return 0;
}

经过我们计算和分析,发现上面三段 代码输出的结果是一样的。why?

  • 有符号的char类型(signed char)取值范围:-128~127
  • 无符号的char类型(unsigned char)取值范围:0~225
  • 截断:超过以上的范围,有一部分数据会被截断,只要存储在内存中的数据必须是在以上范围内。

NO3.

 请问下面这段代码输出什么?

3.
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);

//按照补码的形式进行运算,最后格式化成为有符号整数

#include<stdio.h>
int main()
{
int i = -20;
//10000000 00000000 00000000 00010100
//11111111 11111111 11111111 11101011
//11111111 11111111 11111111 11101100补码
unsigned int j = 10;
//00000000 00000000 00000000 00001010原反补相同
printf("%d\n", i + j);
//11111111 11111111 11111111 11110110补码
//10000000 00000000 00000000 00001010原码
//-10
return 0;
}

NO4.

下面这段代码输出什么? unsigned int的范围

4.
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}

NO5.

 下面这段代码输出什么?signed char的范围

5.
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}

NO6.

 下面这段代码输出什么?unsigned char的范围

6.
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}

总结 

有符号整型signed char 

 

 无符号整型unsigned int

  •  有符号整型signed char的取值范围:127 ~  -128
  • 无符号整型unsigned char的取值范围:0~255

同理我们可以将以上代码应用于其他整型short/int/long等等。总结出它们的取值范围。特别注意千万别掉进无符号整型的陷阱了!!🆗🆗🆗

例如:short两个字节 16个比特位

  • 有符号整型signed short的取值范围:-32768~32767
  • 无符号整型unsigned short的取值范围:0~65635

同理大家自己动手总结一下整型类型的取值范围。

关于浮点数的存储会在下篇博文讲解,同时也会去总结二进制中的知识和易错混点。

✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正。

代码-----------------→【gitee:https://gitee.com/TSQXG】

联系-----------------→【邮箱:2784139418@qq.com】

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

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

相关文章

计蒜客T1266——出勤记录

水题&#xff0c;唯一考验操作水平的只有同级连续字符串最大值这一操作&#xff0c;解决方式如下&#xff1a; int late-1; //连续缺勤的次数 int max0;//最长连续的L //缺勤检验 for(int k0;k<temp.size()-1;k){if(temp[k]L&&late-1){late1;//当前是连续的第一个…

26、springboot的自动配置03--核心功能--自定义条件注解及使用

开发自己的自动配置------开发自己的条件注解 ★ 自定义条件注解 好处有两个&#xff1a; 1. 真正掌握Spring boot条件注解的本质。 2. 项目遇到一些特殊的需求时&#xff0c;也可以开发自己的自定义条件注解来解决问题。自定义条件注解&#xff1a; ▲ 所有自定义注解其实都…

1.flink快速入门

前言 下图表示的是一个简单的flink-job的计算图&#xff0c;这种图被称为DAG(有向无环图)&#xff0c;表示的这个任务的计算逻辑&#xff0c;无论是spark、hive、还是flink都会把用户的计算逻辑转换为这样的DAG&#xff0c;数据的计算按照DAG触发&#xff0c;理论上只要构建出…

计算机竞赛 卷积神经网络手写字符识别 - 深度学习

文章目录 0 前言1 简介2 LeNet-5 模型的介绍2.1 结构解析2.2 C1层2.3 S2层S2层和C3层连接 2.4 F6与C5层 3 写数字识别算法模型的构建3.1 输入层设计3.2 激活函数的选取3.3 卷积层设计3.4 降采样层3.5 输出层设计 4 网络模型的总体结构5 部分实现代码6 在线手写识别7 最后 0 前言…

Android Studio Giraffe控制台乱码

这几天在使用Android Studio Giraffe进行一个App的开发&#xff0c;在项目构建的时候&#xff0c;控制台输出中文都是乱码&#xff0c;看着很不爽&#xff0c;进行了两项配置&#xff0c;中文就可以正常输出了&#xff0c;看起来就爽多了。 第一个配置&#xff1a;点击Help菜单…

系统架构设计专业技能 · 信息系统基础

系列文章目录 系统架构设计专业技能 网络技术&#xff08;三&#xff09; 系统架构设计专业技能 系统安全分析与设计&#xff08;四&#xff09;【系统架构设计师】 系统架构设计高级技能 软件架构设计&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 …

这些Linux基础命令你总得掌握吧

B站|公众号&#xff1a;啥都会一点的研究生 写在前面 很多深度学习/机器学习/数据分析等领域&#xff08;或者说大多数在Python环境下进行操作的领域&#xff09;的初学者入门时是在Windows上进行学习&#xff0c;也得益于如Anaconda等工具把环境管理做的如此友善 但如果想在…

【Unity每日一记】SceneManager场景资源动态加载

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

【CAM】CAM(Class Activation Mapping)——可视化CNN的特征定位

文章目录 一、CAM(Class Activation Mapping)二、CAM技术实现2.1 网络修改2.2 微调2.2 特征提取 三、总结Reference 完整代码见Github &#xff1a;https://github.com/capsule2077/CAM-Visualization &#xff0c;如果有用可以点个Star&#xff0c;谢谢&#xff01; 一、CAM(C…

视频转云存的痛点

现在运营商体系里面&#xff0c;有大量的视频转云存储的需求&#xff0c;但是视频云存储有一个比较大的痛点&#xff0c;就是成本&#xff01; 成本一&#xff1a;存储成本&#xff1b; 我们以1000路2M视频转云存&#xff0c;存储时间为90天为例&#xff08;B端存储时间有时候…

Java | IDEA中 jconsole 不是内部或外部命令,也不是可运行的程序

解决办法&#xff1a; 1.先将Terminal的Shell path 修改为C:\WINDOWS\system32\cmd.exe 2.在检查环境变量中的ComSpec的值 3.找到自己电脑下载的jdk的bin的地址 4.将jdk的bin地址加入到系统变量path中

仪表板展示 | DataEase看中国:2023年中国电影市场分析

背景介绍 随着《消失的她》、《变形金刚&#xff1a;超能勇士崛起》、《蜘蛛侠&#xff1a;纵横宇宙》、《我爱你》等国内外影片的上映&#xff0c;2023年上半年的电影市场也接近尾声。据国家电影专资办初步统计&#xff0c;上半年全国城市院线票房达262亿元&#xff0c;已经超…

Mariadb高可用MHA (四十二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 1.1 概念 1.2 组成 1.3 特点 1.4 工作原理 二、构建MHA 2.1 ssh免密登录 2.2 主从复制 2.3 MHA安装 2.3.1所有节点安装perl环境 2.3..2 node 2.3.…

SpringBoot + Vue 微人事权限组管理模块 (十四)

权限组前端页面制作 权限组管理角色和菜单之间关系&#xff0c;操作员管理着用户和角色之间的关系。 英文的输入框要有个前缀&#xff0c;SpringSecurity里角色英文名需要加一个ROLE_的前缀 上代码 <div><div class"permissManaTool"><el-input pla…

完全备份、增量备份、差异备份、binlog日志

Top NSD DBA DAY06 案例1&#xff1a;完全备份与恢复案例2&#xff1a;增量备份与恢复案例3&#xff1a;差异备份与恢复案例4&#xff1a;binlog日志 1 案例1&#xff1a;完全备份与恢复 1.1 问题 练习物理备份与恢复练习mysqldump备份与恢复 1.2 方案 在数据库服务器192…

【图论】Floyd算法

一.简介 Floyd算法&#xff0c;也称为Floyd-Warshall算法&#xff0c;是一种用于解决所有节点对最短路径问题的动态规划算法。它可以在有向图或带权图中找到任意两个节点之间的最短路径。 Floyd算法的基本思想是通过中间节点逐步优化路径长度。它使用一个二维数组来存储任意两…

java面试基础 -- ArrayList 和 LinkedList有什么区别, ArrayList和Vector呢?

目录 基本介绍 有什么不同?? ArrayList的扩容机制 ArrayLIst的基本使用 ArrayList和Vector 基本介绍 还记得我们的java集合框架吗, 我们来复习一下, 如图: 可以看出来 ArrayList和LinkedList 都是具体类, 他们都是接口List的实现类. 但是他们底层的逻辑是不同的, 相信…

RabbitMq交换机类型介绍

RabbitMq交换机类型介绍 在RabbitMq中&#xff0c;生产者的消息都是通过交换器来接收&#xff0c;然后再从交换器分发到不同的队列&#xff0c;再由消费者从队列获取消息。这种模式也被成为“发布/订阅”。 分发的过程中交换器类型会影响分发的逻辑。 直连交换机&#xff1a…

【Go】Go 文本匹配 - 正则表达式基础与编程中的应用 (8000+字)

正则表达式&#xff08;Regular Expression, 缩写常用regex, regexp表示&#xff09;是计算机科学中的一个概念&#xff0c;很多高级语言都支持正则表达式。 目录 何为正则表达式 语法规则 普通字符 字符转义 限定符 定位符 分组构造 模式匹配 regexp包 MatchString…

什么是Eureka?以及Eureka注册服务的搭建

导包 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 htt…