【C语言进阶】深度剖析数据在内存中的存储--上

news2025/1/21 14:08:46

1. C语言中的数据类型的简单介绍

注:C99标准里面,定义了bool类型变量。这时,只要引入头文件stdbool.h ,就能在C语言里面正常使用bool类型。

在这里插入图片描述
1.1 在C语言中各类型所占内存空间的大小如下

char类型的数据类型大小为1字节即8比特位。

short类型的数据类型大小为2字节即16比特位。

int类型、float类型的数据类型大小为4字节即32比特位。
long类型较为特殊,C语言规定中sizeof(long)>=sizeof(int)
32位平台下long大小为4字节,64位平台下long大小为8字节。
long long类型、double类型的数据类型大小为8字节即64位。

1.2 类型的意义:

  1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
  2. 如何看待内存空间的视角
    什么叫做看待内存空间的视角呢?以int类型、float类型为例,虽然大小都为4字节,但是存储的不同的数据类型。

1.3 类型的基本归类:
整型家族:

char类型在内存中以ASCLL码值存储,所以归类于整型家族
注:在C语言标准中,char类型默认为unsigned char 还是signed char是未定义的,取决于编译器,但是大部分编译器char默认为signed char
char

  unsigned char   signed char

short

unsigned short   signed short

int

int unsigned int   signed int

long

unsigned long   signed long

long long

unsigned long long   signed long long

有符号类型的最高位表示符号位,负数最高位是1,正数最高位是0。

浮点数家族:

float
double

构造类型:

数组类型

数组类型是去掉数组名,剩下的部分。
例如int arr1[5]和int arr2[8]两个数组的类型分别是int [5]和int [8].

结构体类型 struct
枚举类型 enum
联合类型 union

指针类型

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

空类型:

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

2. 整形在内存中的存储

我们知道数值有不同的表示方式.
例如十进制的21,用不同进制表示如下:
二进制表示:0b10101 (二进制以0b开头)
八进制表示:025 (八进制以0开头)
十六进制表示:0x15 (十六进制以0x开头)
而在计算机中数据是以2进制存储的。

2.1 原码、反码、补码

计算机中的整数有三种表示方法,即原码、反码和补码。 三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,
正整数的原码、反码、补码都相同。
负整数的三种表示方法各不相同。
原码 直接将二进制按照正负数的形式翻译成二进制就可以。
反码 将原码的符号位不变,其他位依次按位取反就可以得到了。
补码 反码+1就得到补码。

以正整数20和负整数10为例,原码反码补码如下。
数据在内存中是以二进制存储的,但为了方便程序员观察,在编译器的内存窗口显示的是16进制
在这里插入图片描述

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

2.2为什么要使用补码存储呢?

举个例子 计算机计算1-1是如何实现的呢,因为(CPU只有加法器)可以将1-1变为1+(-1) 假设都是短整型数据
1的原码是0000000000000001
-1的原码是1000000000000001
相加的结果是1000000000000010 //-2
1+(-1)的结果不应该是0么?这里的结果却是-2.
🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔
通过上面的例子我们可以看到,如果采用原码存储,不便于加减运算。无法直接得到计算结果。 而如果使用补码存储 假设都是短整型数据
1的补码是0000000000000001
-1的补码是111111111111111111
相加的结果是0000000000000000 // 0
通过上面的例子我们可以看到,如果采用补码存储,可以可以将符号位和数值域统 一处理,直接得到运算的结果。

补码与原码相互转换,其运算过程 是相同的,不需要额外的硬件电路。
这句话是什么意思呢?

我们知道负整数的补码就是将原码的符号位不变,其他位依次按位取反再加1 那么知道了它的补码如何求源码呢?
将运算过程逆过来,负整数的补码-1就是反码,而反码再符号位不变,其他位按位取反就是原码,这是一种普遍的方法。
但是其实负整数的补码转换为原码也可以采用原码转换为补码时采用的方法 将补码符号位不变,其他位按位取反,再将得到的结果加1就是负整数的原码
例如-10的补码转换为原码:
在这里插入图片描述

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

2.3 大小端介绍

什么大端小端: 大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。 为什么有大端和小端:
为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元 都对应着一个字节,一个字节为8bit。但是在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年系统工程师笔试题:
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。
#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;
}

3.练习巩固

学习了上面诸多知识后,让我们来实践一下吧。

1.打印a,b,c的结果分别是什么?
注:signed char 取值范围-128~127 unsigned char取值范围0-255

#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类型在vs编译器下默认是 signed char,将 -1存到signed char中会发生截断,-1默认是一个32位的整数。存到signed char中会截断低8位存储,所以a和b里存放的是11111111,而%d是打印有符号的整型数值,所以打印时会发生整型提升,提升时看a,b的类型,ab都是有符号类型,所以我们看它的最高位(符号位)来进行提升,这里的最高位是1,所以提升时在高位补24个1变为11111111111111111111111111111111,这时我们再将补码转换为原码1000000000000000000000000001得到的就是最终打印出来的结果的2进制序列,转换为10进制就是 -1,所以打印a,b的结果是 -1 .
  而c里存放的也是8个1,但是整型提升时因为是无符号类型,所以高位直接补24个0,凑齐32比特位。得到的补码是00000000000000000000000011111111,再将补码转换为原码依旧是00000000000000000000000011111111转换为10进制就是255,所以打印c的结果是 255。

2. 打印a的结果是什么?

#include <stdio.h>
int main()
{
    signed char a = -128;
    printf("%u\n",a);//%u打印无符号整数
    return 0;
    }

解析:
  -128的补码是11111111111111111111111110000000,截断低8位10000000,以%u形式打印发生整型提升,因为signed
char为有符号类型所以高位补符号位变为11111111111111111111111110000000,因为是以%u形式打印,所以会认为这串补码是一串非常大的正数的二进制序列,因为是正数所以补码原码相同,转换为10进制就是4294967168,所以a打印出来就是4294967168。

3.打印a的结果分别是是什么?

#include <stdio.h>
int main()
{
    signed char a = 128;
    printf("%u\n",a);  //4294967168
    printf("%d\n",a); //-128
    return 0;
}

答案: printf(“%u\n”,a); //4294967168
printf(“%d\n”,a); //-128

4…打印i的结果是什么?

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

答案:9 8 7 6 5 4 3 2 1 0 4294967295 4294967294 4294967293 …死循环下去
为什么结果会是这样呢? 解析: 因为i是一个无符号整数,所以9~0都是正常循环打印的,但是i–到了-1的时候,因为unsigned int
i是无符号整数,所以不会将-1的补码11111111111111111111111111111111看作是一个负数,而是会看作一个很大的正数,所以依旧满足循环条件。

在这里插入图片描述
5.字符串a的长度是多少?

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

解析:a[i]里存放的值依次是-1,-2,-3 …到-128为一个轮回,然后变为127,126
…2,1,0,然后再依次是-1,-2,-3
…一直循环到数组存满为止。本题求的是字符串长度,strlen在字符数组里找到‘\0’为止,而‘\0’的ascll码值为0,所以字符串a的长度是255。
在这里插入图片描述

6.下面代码的运行结果是什么?

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

答案:无限打印hello world,死循环下去。
解析:无符号数到255后+1又会变为0,无限循环下去。

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

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

相关文章

爬爬爬——今天是浏览器窗口切换和给所选人打钩(自动化)

学习爬虫路还很长&#xff0c;第一阶段花了好多天了&#xff0c;还在底层&#xff0c;虽然不是我专业要学习的语言&#xff0c;和必备的知识&#xff0c;但是我感觉还挺有意思的。加油&#xff0c;这两天把建模和ai也不学了&#xff0c;唉过年了懒了&#xff01; 加油坚持就是…

16 亚稳态原理和解决方案

1. 亚稳态原理 亚稳态是指触发器无法在某个规定的时间段内到达一个可以确认的状态。在同步系统中&#xff0c;输入总是与时钟同步&#xff0c;因此寄存器的setup time和hold time是满足的&#xff0c;一般情况下是不会发生亚稳态情况的。在异步信号采集中&#xff0c;由于异步…

MySQL篇----第二十二篇

系列文章目录 文章目录 系列文章目录前言一、什么是表级锁二、什么是页级锁三、什么是行级锁四、什么是悲观锁前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、…

2023-12蓝桥杯STEMA 考试 Python 中高级试卷解析

蓝桥杯STEMA 考试 Python 中高级试卷&#xff08;12 月&#xff09; 一、选择题 第一题 以下哪项是取余运算符&#xff1f;&#xff08; C &#xff09; A、* B、// C、% D、 第二题 已知&#xff1a;s "python"&#xff0c;执行 print(s[::2])语句后&…

【Java程序设计】【C00265】基于Springboot的地方废物回收机制管理系统(有论文)

基于Springboot的地方废物回收机制管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的地方废物回收机构管理系统 本系统分为管理员功能模块以及员工功能模块。 管理员功能模块&#xff1a;管理员登录系统后…

使用matplotlib库来绘制柱状图

# coding: utf-8 from matplotlib import pyplot as plt from matplotlib import font_manager# 定义区间和宽度列表 interval [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 60, 90] width [5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 30, 60] # 定义数量列表 quantity [836, 2737, 3723, …

【QT+QGIS跨平台编译】之三十六:【RasterLite2+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、RasterLite2介绍二、文件下载三、文件分析四、pro文件五、编译实践一、RasterLite2介绍 RasterLite2是一个开源的轻量级栅格数据库,可以用于存储和管理各种类型的栅格数据,包括卫星遥感图像、数字高程模型等。 与传统的GIS数据存储方式不同,RasterLite2采用基…

【程序设计竞赛】C++与Java的细节优化

必须强调下&#xff0c;以下的任意一种优化&#xff0c;都应该是在本身采用的算法没有任何问题情况下的“锦上添花”&#xff0c;而不是“雪中送炭”。 如果下面的说法存在误导&#xff0c;请专业大佬评论指正 读写优化 C读写优化——解除流绑定 在ACM里&#xff0c;经常出现…

基于Qt的人脸识别项目(功能:颜值检测,口罩检测,表情检测,性别检测,年龄预测等)

完整代码链接在文章末尾 效果展示 代码讲解(待更新) qt图片文件上传 #include <QtWidgets> #include <QFileDialog>

普通男孩的新年创作纪念日

前言 首先在新春佳节&#xff0c;小编在这里祝各位大佬。萌新友友们新年好&#xff0c;希望每一个烟火般的你在新的一年里 offer 多多&#xff0c;薪资多多 &#xff0c;龙行龘龘 &#x1f409; &#x1f409; &#x1f409; &#x1f409;&#xff0c;前程朤朤 ❤️ ❤️ ❤…

Ps:堆栈模式在摄影后期的应用

Photoshop 的堆栈模式 Stack Mode为摄影师提供了一种强大的后期处理能力&#xff0c;通过堆叠和处理多张照片来实现无法单靠一张照片完成的效果。 正确的前期拍摄策略和后期处理技巧可以显著提高最终图像的质量和视觉冲击力。 ◆ ◆ ◆ 前期拍摄通用注意事项 在前期拍摄时&am…

【排序】快速排序

基本思想 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;右子序列中所…

视频讲解:优化柱状图

你好&#xff0c;我是郭震 AI数据可视化 第三集&#xff1a;美化柱状图&#xff0c;完整视频如下所示&#xff1a; 美化后效果前后对比&#xff0c;前&#xff1a; 后&#xff1a; 附完整案例源码&#xff1a; util.py文件 import platformdef get_os():os_name platform.syst…

STM32 寄存器操作 GPIO 与中断

一、如何使用stm32寄存器点灯&#xff1f; 1.1 寄存器映射表 寄存器本质就是一个开关&#xff0c;当我们把芯片寄存器配置指定的状态时即可使用芯片的硬件能力。 寄存器映射表则是开关的地址说明。对于我们希望点亮 GPIO_B 的一个灯来说&#xff0c;需要关注以下的两个寄存器…

Linux---网络套接字

端口号 端口号 端口号是一个2字节16位的整数; 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理; IP地址 端口号能够标识网络上的某一台主机的某一个进程; 一个端口号只能被一个进程占用 在公网上&#xff0c;IP地址能表示唯一的一台主机&…

大模型激活函数知识

FFN块 计算公式 在Transformer模型中&#xff0c;FFN&#xff08;Feed-Forward Network&#xff09;块通常指的是在编码器&#xff08;Encoder&#xff09;和解码器&#xff08;Decoder&#xff09;中的一个全连接前馈网络子结构。FFN块位于自注意力层&#xff08;Self-Attent…

C语言第二十三弹---指针(七)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、sizeof和strlen的对比 1.1、sizeof 1.2、strlen 1.3、sizeof 和 strlen的对比 2、数组和指针笔试题解析 2.1、⼀维数组 2.2、二维数组 总结 1、si…

Java 基于微信小程序的私家车位共享系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

WebSocket原理详解

目录 1.引言 1.1.使用HTTP不断轮询 1.2.长轮询 2.websocket 2.1.概述 2.2.websocket建立过程 2.3.抓包分析 2.4.websocket的消息格式 3.使用场景 4.总结 1.引言 平时我们打开网页&#xff0c;比如购物网站某宝。都是点一下列表商品&#xff0c;跳转一下网页就到了商品…