C语言——数据在内存中的存储(上)

数据在内存中的存储

1. 数据类型的介绍

之前已经介绍过C语言中的基本数据类型了,主要有:

  • char //字符数据类型
  • short //短整型
  • int //整形
  • long //长整型
  • long long //更长的整形
  • float //单精度浮点数
  • double //双精度浮点数

注意:C语言中是是没有字符串类型的。

类型的意义:

  1. 使用这种类型的数据所开辟的内存空间的大小。
  2. 如何看待内存空间的视角。

2. 类型的基本分类

【整形家族】

char :unsigned char signed char

short :unsigned short signed short

int :unsigned int signed int

long :unsigned long signed long

long long :unsigned long long signed long long

注意:C语言规定:sizeof(long)>=sizeof(int),所以long类型的占用的空间不能确定是4还是8。

【浮点数家族】

float

double

【构造类型】

数组类型

结构体类型

枚举类型

联合类型

【指针类型】

int *pi;

char *pc;

float* pf;

void* pv;

3. 整形在内存中的存储

由于变量的创建是需要空间的,具体使用的空间的大小是根据不同的类型而确定的。例如:

char ch = 0;这里ch变量是char类型,所以就在内存中占用了一个字节。

注意char类型一般C语言官方没有明确规定是 signed char还是 unsigned char,一般的编译器,例如VS上,char就是signed char 。但是除了char以外,其他的整形都是有明确规定的,例如:int就是signed int

那么不同的数据类型所能表示的范围是多少呢?我们可以通过以下代码来查看:

#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
int main()
{printf("%d\n", INT_MAX);printf("%d\n", INT_MIN);return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-133iB8YJ-1685460890411)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528135439546.png)]

那么这些数据的范围大小是怎么计算出来的呢?这里以char为例:

char占用一个字节:一个字节有8个比特位,每一个比特位只能是0或1,所以char类型在内存中组合方式一共就有256种:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXcfGFbt-1685460890412)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528144545767.png)]

注意这里图中所有的二进制序列都是代表的是内存中的补码。由此观之,char类型的数据范围就是:-128~127。unsigned char的范围就是0~255。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6k6czyBp-1685460890412)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528145453042.png)]

由此类推:short数据范围就是:-32768~32767。其他的整数数据类型的范围小伙伴们可以自行查阅。

3.1 整形在内存中的存储

计算机中保存整数二进制的方式主要有三种,分别是原码反码补码整形在内存中主要是以补码的形式保存。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位则是直接读取即可。

正数的原、反、补码都相同。

负整数的三种表示方法各不相同。

原码:直接将数值按照正负数的形式翻译成二进制就可以得到原码。

补码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

反码+1就得到补码。

对于整形来说数据存放内存中其实存放的是补码。使用补码可以将其符号位和数值域进行统一运算。

原因:

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

对于数据存放内存中存放的是补码我们可以通过编译器进行直接观察。例如:-1的补码是32个1,用16进制表示就是全f。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpqakovm-1685460890413)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528141952454.png)]

但我们把例子换成4的时候:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EHJdZDxY-1685460890413)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528142156157.png)]

这里发现内存中是有低地址到高地址存放数据的。数据的低权值位是放在低地址处的。这里就要引出新概念了:大端字节序和小端字节序。

4. 大小端介绍

概念:

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

小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。

为什么有大端和小端

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为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处理器还可以由硬件来选择是大端模式 还是小端模式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5g4vpl2R-1685460890414)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528142934825.png)]

字节序以字节为单位讨论数据的存储的。一个char类型只占用一个字节,所以对char类型讨论大小端字节序是没有意义的,这里大小端字节序是针对占用的内存空间大于1个字节的整数数据类型的。

大小端字节序是由电脑内置部件决定的与编译器的类型无关。这里作者的电脑是以小端字节序存储的。

4.1 练习

Q1

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

Answer:

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

以下是错误的写法:

int main()//这种是错误的
{int a = 0x11223344;char b = (char)a;//无论如何b拿到的都是a的最低字节的数据 if (b == 0x44)printf("小端!\n");if (b == 0x11)printf("大端!\n");return 0;
}

上面这段代码无论如何b拿到的都是a的最低字节的数据

Q2

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

char a= -1;//-1的二进制补码是32个1。因为char只有一个字节,存放不下,先发生截断,a中存放的就是8个1。

unsigned char c = -1;//c也是只有1个字节,发生截断,存放的也是8个1。

printf("a = %d,c = %d",a,c);执行时,由于%d代表的是有符号打印,所以a和c均会发生整形提升:

先看a的整形提升:a是有符号数,整形提升时补的是符号位,所以就补1,变成32个1,又因为是以有符号的形式打印,而符号位又是1,所以将32个1翻译成原码就是-1,即打印-1.

再看b的整形提升,b是无符号数,整形提升时,最高位补0,所以b就变成了24个0和8个1,又因为是以有符号的形式打印,而符号位是0,翻译成原码就是255。

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VnpFNqgL-1685460890414)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528145735159.png)]

Q3

//输出什么?
#include <stdio.h>
int main()
{char a = -128;printf("%u\n",a);return 0;
}

-128的

原码:100000000000000000000000010000000

反码:111111111111111111111111101111111

补码:111111111111111111111111110000000

由于a只有8比特的空间,所以发生截断,a中存放的是:10000000

在执行 printf("%u\n",a);语句时,因为%u是无符号整形打印:所以a会发生整形提升,由于a是signed char,为有符号类型,整形提升时高位补符号位的数,也就是补1,所以此时a中存放的是:11111111111111111111111110000000,因为是%u无符号打印,所以直接将这串二进制序列看作原码进行打印。

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WN0RLHE5-1685460890414)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528150508845.png)]

Q4

//输出什么?
#include <stdio.h>
int main()
{char a = 128;printf("%u\n",a);return 0;
}

先写出128的补码,再截断存储到a中,a中存放的也是:10000000,与Q3类似。

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ciQP3UZd-1685460890415)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528150659634.png)]

Q5

int main()
{//输出什么?int i = -20;unsigned  int  j = 10;printf("%d\n", i + j);//按照补码的形式进行运算,最后格式化成为有符号整数return 0;
}

先写出i的

原码:10000000000000000000000000010100

反码:11111111111111111111111111101011

补码:11111111111111111111111111101100

写出j的

补码:00000000000000000000000000001010

接着让这两个补码相加:

11111111111111111111111111101100+

00000000000000000000000000001010=

11111111111111111111111111110110

又因为是%d以有符号整形进行打印,所以将相加之后的二进制的最高位看作符号位。所以这里将相加得到的二进制序列转换成原码:10000000000000000000000000001010,也就是-1。

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vxadLC1q-1685460890415)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528151358092.png)]

Q6

//输出什么?
unsigned int i;
for(i = 9; i >= 0; i--)
{printf("%u\n",i);
}

这里由于i的数据类型是unsigned int 类型,是恒>=0的,所以I>0这个条件会一直满足,程序发生死循环。

运行结果:发生死循环

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P9xU8IBl-1685460890415)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528151504019.png)]

Q7

//输出什么?
int main()
{char a[1000];int i;for(i=0; i<1000; i++){a[i] = -1-i;}printf("%d",strlen(a));return 0;
}

这里arr[i]的值一开始是-1,-2,-3……当arr[i]的值变成-128时,,由本文之前画的图可知,此时再减1就会变成127,接着就是126,125,……1,0.这里strlen计算数组的长度时,会遇到’\0’才停止,而’\0’的ascll码值就是0,即这里数组的长度就是当arr[i]变成0之前的元素的个数,这里由-1到-128,再由-128到127再到1,一共有255个元素。所以结果就是255.

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wAHbsYh1-1685460890416)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528151546746.png)]

Q8

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

此处由于i的数据类型是unsigned char 其数据范围是[0,255],始终是大于0的,所以会一直打印,发生死循环。

运行结果:发生死循环

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jTcEiukT-1685460890416)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230528151616258.png)]

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

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

相关文章

php图形 验证码代码,PHP制作图形验证码代码分享,php图形验证码代码_PHP教程

PHP制作图形验证码代码分享,php图形验证码代码 效果: myvcode.class.php:封装创建验证码的类 /* * file:myvcode.class.php * 验证码类,类名Vcode */ class Vcode {private $width; /*验证码宽度*/ private $height; /*验证码高度*/ private $codeNum; /*验证码字符个数*/ p…

Android图形验证码

1. 前言 图形验证码可以让服务器以图片的形式传给客户端&#xff0c;也可以让客户端自己实现。那客户端要怎么做呢&#xff1f;其实很简单&#xff0c;可以使用Android的Canvas、Paint和Random来实现。用Random来随机生成数字、字母、颜色、画笔原点等等&#xff0c;设置Paint…

java生成图形验证码

随时随地阅读更多技术实战干货&#xff0c;获取项目源码、学习资料&#xff0c;请关注源代码社区公众号(ydmsq666) 首先&#xff0c;需要生成验证码字符串&#xff0c;方式很多&#xff0c;下面提供一种&#xff0c;根据指定源的方式来生成验证码 /*** 使用系统默认字符源生成验…

图形验证码最佳攻略2

下面是注册 如果是手机用户注册,需要发送短信验证码 说明: 发送图形验证码是为了拦截发送短信的.但是不拦截"注册帐号" 但是,用户体验很别扭,因为图形验证码很显然是错误的,但是却可以注册成功. 如果点击注册帐号 ,也要校验图形验证码,那就让用户输入两次图形验证码,…

小程序图形验证码输入校验例子

前言 本教程是基于 “apifm-wxapi” 模块&#xff0c;教你快速实现小程序开发&#xff0c;所以你可能需要先了解以下知识点&#xff1a; 《创建 HelloWorld 项目》《使用 “apifm-wxapi” 快速开发小程序》《免费注册开通后台&#xff0c;获得专属域名》 功能说明 图形验证码的…

Part1:使用 TensorFlow 和 Keras 的 NeRF计算机图形学和深度学习——计算机图形学世界中相机的工作原理

Part1&#xff1a;使用 TensorFlow 和 Keras 的 NeRF计算机图形学和深度学习 1. 效果图2. 原理2.0 前向成像模型2.1 世界坐标系2.2 相机坐标系2.3 坐标变换2.4 投影转换2.5 数据 3. 源码参考 是否有一种方法可以仅从一个场景多张不同视角的照片中捕获整个3D场景&#xff1f; 有…

IDEA+Mysql+Sqlserver安装步骤_kaic

下载Intellij 开发工具&#xff0c;如果有请检查软件是否过期&#xff0c;如果过期卸载电脑上的Intellij软件。卸载步骤&#xff1a; 打开控制面板&#xff0c;选择卸载程序找到Intellij右键卸载 如果没有请保存文档中的Intellij.zip压缩包,进行安装&#xff0c;安装步骤 双…

电脑重置网络

1、键盘WinR键&#xff0c;弹出窗口 2、然后在里面输入cmd输入CMD 3、出现的命令提示框内输入“netsh winsock reset"按”Enter“键 4、重启电脑后生效。

重置电脑

步骤1&#xff1a; 以Win10系统为例 直接在搜索框输入:reset 或者直接选择「设置」-「更新和安全」-「恢复」 步骤2&#xff1a; 步骤3&#xff1a; 根据个人情况选择【保留我的文件】或者【删除所有内容】

如何让Win10 重置此电脑功能无法使用

环境&#xff1a; Win10 专业版 问题描述&#xff1a; 通过设置-更新和安全-恢复-重置此电脑&#xff0c;如何让Win10 重置此电脑功能无法使用 解决方案&#xff1a; 1.PE下删除Win Re 恢复分区&#xff0c;然后重置就无法使用

重置计算机后无法开机,win10重置此电脑失败怎么办_win10重置此电脑失败无法开机修复方法...

当win10系统使用时间长了&#xff0c;难免会有一些电脑故障的出现&#xff0c;这时有些用户就会选择使用重置电脑的方式来解决&#xff0c;但是最近有用户再给自己的win10系统进行重置时总是出现失败的情况&#xff0c;那么win10重置此电脑失败怎么办呢&#xff1f;下面就来告诉…

win10怎么重置计算机,如何重置Win10系统电脑

当系统出现一些难以解决的问题时&#xff0c;我们一般会选择重置电脑来解决问题&#xff0c;比起重装电脑来说简单很多&#xff0c;但是也要注意有可能会失败。下面小编就以win10为例&#xff0c;给大家讲讲怎么重置电脑的操作步骤吧。 操作步骤&#xff1a; 1、打开屏幕侧方的…

DELL 笔记本 - Windows 10 恢复 / 重置此电脑

DELL 笔记本 - Windows 10 恢复 / 重置此电脑 1. Windows 设置 2. 更新和安全 3. 恢复 4. 删除所有内容 5. 所有驱动器 6. 仅删除我的文件 7. 重置 References https://yongqiang.blog.csdn.net/

win10系统如何重置电脑

在win10系统出现系统问题无法修复的时候&#xff0c;我们可以尝试使用win10系统自带的重置功能&#xff0c;相比重装系统在操作上可能要简单不少&#xff0c;不过同样也有失败的风险。下面就让小编带领大家进行一下win10系统重置电脑的操作吧。 win10系统如何重置电脑 1、打…

win10怎样重置电脑

win10怎样重置电脑 windows10提供重置电脑的功能&#xff0c;如果系统遇到问题&#xff0c;运行不正常&#xff0c;或者想刷新系统&#xff0c;可以考虑重置电脑&#xff0c;使电脑有一个全新的干净的系统。下面介绍重置的方法 点击开始菜单&#xff0c;然后选择“设置” 在设…

【教程】Win10重置电脑和重装系统

如果电脑系统出现蓝屏或者卡顿的故障&#xff0c;很多用户会想要通过重装系统来解决。 其实在Windows10系统中会有“重置此电脑”的功能&#xff0c;类似于恢复出厂设置的意思。很多时候只需要重置电脑就足够解决用户的需求了&#xff0c;duck不必繁琐的制作启动U盘来重装系统…

计算机系统如何重置,如何重置电脑系统?看这里1分钟教会你!

原标题&#xff1a;如何重置电脑系统&#xff1f;看这里1分钟教会你&#xff01; 哈喽&#xff0c;大家好我是小黑~最近后台有小伙伴留言咨询#如何重置Windows 10系统&#xff1f;#。 重置系统是Windows系统自带的功能&#xff0c;此功能会将错误的系统文件替换&#xff0c;从而…

Win10笔记本电脑怎么直接重置初始化

很多朋友都知道电子设备一般都会有初始化的功能&#xff0c;自己使用的电脑毛病越来越多&#xff0c;不知道能不能重置初始化&#xff0c;今天我给朋友们讲讲Win10笔记本电脑怎么直接重置初始化让电脑系统焕然一新&#xff0c;大家可以按下面的步骤操作。 Win10笔记本电脑怎么直…

重装也无法修复此计算机,win10系统重置此电脑失败怎么解决

win10系统重置失败怎么办呢?有时候因为电脑各种各样的问题我们需要进行重置系统,可是有些粗心的朋友忘记给笔记本充电了。造成win10系统重置失败的情况。下面,我就给大家介绍一下win10系统重置失败的解决方法 win10系统是微软安全性最高的一款版本,其游戏性能以及易用性也深…

如何给电脑系统重置系统?方法其实很简单

Win11怎么一键重置&#xff1f;很多朋友感觉电脑系统遇到比较大的问题&#xff0c;必须要进行重置&#xff0c;但就是不知道如何操作&#xff0c;今天小编带来了Win11一键重置电脑的操作步骤&#xff0c;一种方法是在电脑还能进入桌面的时候进行操作&#xff0c;另一种则是电脑…