当前位置:网站首页>【C语言进阶】数据的存储【上篇】【万字总结】
【C语言进阶】数据的存储【上篇】【万字总结】
2022-06-10 18:27:00 【你我皆为凡人】
作者:你我皆为凡人
博客主页:你我皆为凡人的博客
名言警句:时间不会为任何人停留,而事物与人,无时不刻也在变化着。每一个人,也都在不停向前!
觉得博主文章写的不错的话,希望大家三连(关注,点赞,评论),多多支持一下!!
系列作品:

文章目录
目录
前言
本文重点讲解了数据类型的详细介绍与在内存中存放的数值,整形在内存中的存储以及原码反码补码的详细介绍,大小端字节序介绍及其判断,以及7道经典的题型让大家得以巩固知识
提示:以下是本篇文章正文内容,下面案例可供参考
数据类型的介绍
前面我们已经学习了基本的内置类型:
#include<stdio.h>
int main()
{
char 1字节 //字符数据类型
short 2字节 //短整型
int 4字节 //整形
long 4/8字节 //长整型
long long 8字节 //更长的整形
float 4字节 //单精度浮点数
double 8字节 //双精度浮点数
return 0;
}类型的意义:
1,使用这个类型开辟内存空间的大小,而大小决定了使用的范围
2,决定了如何看待内存空间的视角
类型的基本归类:
整型家族:
char
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed long [int]
浮点数家族:
float
double
构造类型:
数组类型
结构体类型 struct
枚举类型 enum
联合类型 union
指针类型:
int *pi;
char *pc;
float* pf;
void* pv;
空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型
整形在内存中的存储
int main()
{
int a = 20;
int b = -10;
return 0;
}我们之前了解过一个变量的创建是要在内存中开辟空间的,空间大小是根据不同的类型而创建的,那么接下来我们谈谈数据在所开辟的内存中到底是如何存储的,比如上面的代码,我们知道a和b分配4个字节的空间,那么是如何存储的呢?
原码,反码,补码
整数可以用二进制,十进制,十六进制,八进制表示,而在内存中是用二进制来展示,而整数的二进制表示有三种表示,原码,反码与补码
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位用0或者1表示
对于负整数的三种表示方法各不相同:
原码:
直接将整数按照正负数的形式表示成二进制就可以
反码:
将原码的符号位不变,其他位依次安位取反就可以得到
补码:
反码+1就得到补码
正数的原,反,补码都相同
而对于整形来说,数据存放内存中其实存放的是补码
所以上图的代码在内存中的存储就是这样的:
int main()
{
int a = 20;
//20 正数
//00000000000000000000000000010100 原码
//00000000000000000000000000010100 反码
//00000000000000000000000000010100 补码
int b = -10;
//-10 负数
//10000000000000000000000000001010 原码
//11111111111111111111111111110101 反码
//11111111111111111111111111110110 补码
return 0;
}
二进制在内存中存储是32位比特位,太长了,一般在内存中以十六进制储存
那么转变过来就是:
int main()
{
int a = 20;
//20 正数
//00000000000000000000000000010100 原码
//0x00000014
//00000000000000000000000000010100 反码
//0x00000014
//00000000000000000000000000010100 补码
//0x00000014
int b = -10;
//-10 负数
//10000000000000000000000000001010 原码
// 0x800000a
//11111111111111111111111111110101 反码
// 0xffffff5
//11111111111111111111111111110110 补码
//0xfffffff6
return 0;
}
可是在内存中具体存放的是哪一个呢?正数的原码反码补码都相同,可是负数的原码反码与补码到底存放的是哪一个呢?接下来就明白了:


我们根据在内存中观察到的十六进制发现存放着的是补码
那么为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统 一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。其实意思就是:1-1在计算机中会转换成1+(-1)那么如何计算呢?00000000000000000000000000000001 110000000000000000000000000000001 -1如果原码相加:10000000000000000000000000000010 -2 结果是错误的,无法计算如果补码相加:00000000000000000000000000000001 1的补码1111111111111111111111111111111111111 -1的补码相加结果:100000000000000000000000000000000 成为了33位比特位,而首位会丢弃,所以为0而补码与原码相互转换其运算过程是相同的,原码可以取反得到反码,反码+1得到补码,而同样,补码可以-1得到反码,反码取反回到原码,但是还可以补码取反+1得到原码比如:-101111111111111111111111111111011010000000000000000000000010011000000000000000000000001010
大小端介绍
我们可以得出结论a与b分别存储的是补码,但是顺序好像有点不对劲,是反着来的,那么这又是为什么,这就涉及到大小端的概念了
什么是大端小端呢?:
大端【字节序】(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;小端【字节序】(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中;而在上面我们可以看到,内存中存放着是小端存储可是为什么会有大端和小端呢:为什么有大端和小端:为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位 的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为 高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式, 刚好相反。我们常用的 X86 结构是 小端模式,而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以 由硬件来选择是大端模式还是小端模式
一道经典笔试题
这是一道百度2015年系统工程师笔试题
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序
如1这个数字,无非就是 0x 00 00 00 01 与0x 01 00 00 00 这两种方式,区别在于第一个字节是否相同,那么如果我们取地址这个数是4个字节,那么强制转换为char类型就是1个字节,刚好是01或者00,而01就是1,00就是0,来进行判别
int main()
{
int a = 1;
if (*(char*)(&a) == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}巩固练习
练习一
//输出什么?
#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;
}现在我们储备一些知识,那么就是如果一个char类型的数值,在内存中有有符号与无符号之分,那么有符号在内存中存放的最大数值为127到-128之内,无符号在内存中存放的最大数值为0-255,那么short类型的呢?如果是无符号在内存中存放的最大数值为0到65535,如果是有符号在内存中存放的最大数值为-32768到32767,而其他的也可以按照二进制而推算出来
解析:
a的值是-1,存放到char类型中但是要以整形打印,-1的二进制为10000000000000000000000000000001 -1的源码
1111111111111111111111111111111111110 -1的反码
1111111111111111111111111111111111111 -1的补码
但是char类型中只能存放1个字节,就是8个比特位,发生了截断
11111111 a的值
%d的打印有符号的整形,所以要整型提升,有符号char根据符号位补齐
1111111111111111111111111111111111111 a的补码,但是打印的是源码
10000000000000000000000000000000
10000000000000000000000000000001 a的源码,也就是最后打印的数值 -1
同理,b的也是有符号char,所以也是-1
c是个无符号char,而无符号char在内存中只能存放0到255,那么如何存放-1呢?
10000000000000000000000000000001 -1的源码
1111111111111111111111111111111111110 -1的反码
1111111111111111111111111111111111111 -1的补码
截断:
11111111
注意无符号的char 整型提升直接补0
000000000000000000000000011111111 补码
而整数的正数原反补都相同,所以打印出来的数为255
练习二
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}char的取值范围在-128到127之间,而a的值在这个范围内,是有符号的char,而要以无符号类型打印出来
10000000000000000000000010000000 -128原码
111111111111111111111111111101111111 -128反码
1111111111111111111111111111110000000 -128补码
截断放入char a中
10000000 -a
整型提升,无符号直接打印1
11111111111111111111111110000000 a的值是一个非常大的数值 4,294,967,168
练习三
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}char的128不在char范围内,先写出原码
10000000000000000000000010000000
截断到char中
10000000
无符号打印,要整形提升,直接写1
11111111111111111111111110000000 a的值最后也是一个非常大的数值 4,294,967,168
练习四
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
//按照补码的形式进行运算,最后格式化成为有符号整数i是整数的-20
10000000000000000000000000010100 -20的原码
11111111111111111111111111101011 -20的反码
11111111111111111111111111101100 -20的补码
j是无符号整数10
00000000000000000000000000001010 10的补码
整数形式打印i+j
11111111111111111111111111101100 -20的补码
00000000000000000000000000001010 10的补码
相加后的结果:
11111111111111111111111111110110 相加后的补码
10000000000000000000000000001001 反码
10000000000000000000000000001010 最后的补码 打印的结果就是-10
练习五
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}定义i是一个无符号的整数,i为9,从9打印到0,然后0-1为-1,而无符号是没有负数的存在的,-1的补码是全1,这是一个很大的数字,往后会是一直打印死循环
练习六
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}char数组里存放1000个元素,a【i】= -1-i;可能我们会想,那么最后的数字不就是-1,-2,-3.。。。到-1000,一千个数嘛 而strlen是求字符串的长度,关注的是字符串中\0(数字0)之前出现过多少字符,而这里面没有\0和数字0,所以是1000,这样想就大错特错了,char的取值范围是-128-127,从-1到-128,下一个会是127-0,那么-128到127之间会有255个数值所以答案是255
练习七
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}定义一个无符号的char类型的i,i小于等于255,要跳出循环得是256,但是无符号char类型的i最大的存储数值为0到255,所以永远不会成为256,所以是死循环
习题练习入口
看完这些不具体操作操作那么是不可以的,可以点击上方直达去练习一些有关习题,也可以随便看一看C语言的一些习题,练习练习选择题和编程题,让自己的知识得到巩固,直接点入标题就可直达,另外想获得大厂内推资格也可以去看看:
边栏推荐
- Morris traversal of binary tree
- How to transform digital transformation? Which way?
- 个人如何投资理财比较安全?
- Design and development of hospital reservation registration platform based on JSP Zip (thesis + project source code)
- Mysql8.0 (summary of new features)
- Adobe Premiere基础-工具使用(选择工具,剃刀工具,等常用工具)(三)
- Longest ascending subsequence (LIS) Logu
- Chapter III data type (II)
- 《Single Image Haze Removal Using Dark Channel Prior》去雾代码实现分析
- [vulnhub range] janchow: 1.0.1
猜你喜欢

Array signal processing simulation part IV -- Z-transform analysis array polynomial

第二章 数据类型(一)
![MySQL advanced Chapter 1 (installing MySQL under Linux) [i]](/img/f9/60998504e20561886b5f62eb642488.png)
MySQL advanced Chapter 1 (installing MySQL under Linux) [i]

SAR回波信号基本模型与性质

基于SSM流量计量云系统的设计与实现.rar(论文+项目源码)

Live broadcast preview | deconstruct OLAP! The new multidimensional analysis architecture paradigm is fully open! Apache Doris will bring five big issues!

Beam pattern analysis based on spectral weighting

Libcurl 7.61.0 vs2013 compilation tutorial

Adobe Premiere foundation - Import and export, merge materials, source file compilation, offline (II)

Data URL
随机推荐
Beam pattern analysis based on spectral weighting
Adobe Premiere Foundation (the last step of video subtitle adding) (6)
Openssl1.1.1 VS2013-编译教程
HelloWorld example of TestNG and how to run it from the command line
Performance and high availability analysis of database firewall
基于ssm在线订餐系统设计与实现.rar(项目源码)
【01】每一位优质作者都值得被看见,来看看本周优质内容吧!
c(指针02)
Detailed explanation of Lora module wireless transceiver communication technology
数据库防火墙的性能和高可用性分析
Screen output of DB2 stored procedure, output parameters, and return result set
基于谱加权的波束方向图分析
Ruixin micro rk1126 platform platform porting libevent cross compiling libevent
Pits encountered during the use of ETL (ETL Chinese garbled)
Dynamic SQL of DB2 SQL pl
单纯形法代码求解(含超详细代码注释和整个流程图)
Adobe Premiere基础-导入导出,合并素材,源文件编译,脱机(二)
lingo12软件下载及lingo语言入门资源
Live broadcast preview | a new era of social interaction, exploring new social experiences in the universe
Longest ascending subsequence (LIS) Logu