当前位置: 首页 > news >正文

C语言第二十八弹---整数在内存中的存储

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】

目录

1、整数在内存中的存储

2、大小端字节序和字节序

2.1、什么是大小端?

2.2、为什么有大小端?

2.3、练习

2.3.1、练习1

2.3.2、练习2

2.3.3、练习3

2.3.4、练习4

2.3.5、练习5

2.3.6、练习6

总结


1、整数在内存中的存储

在讲解操作符的时候,我们就讲过了下面的内容:
整数的2进制表示方法有三种,即原码、反码和补码
三种表示方法均有 符号位和数值位 两部分,符号位都是用 0表示“正”,用1表示“负” ,而数值位最高位(第一位)的⼀位是被当做符号位,剩余的都是数值位。
正整数的原、反、补码都相同。
负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值⼀律用补码来表示和存储。
原因在于,使用补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

2、大小端字节序和字节序

当我们了解了整数在内存中存储后,我们调试看⼀个细节:
#include <stdio.h>
int main()
{int a = 0x11223344;return 0;
}
调试的时候,我们可以看到在a中的 0x11223344 这个数字是按照字节为单位,倒着存储的。这是为什么呢?

2.1、什么是大小端?

其实超过⼀个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储,下面是具体的概念:
大端(存储)模式:是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存在内存的低地址处。
小端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。
上述概念需要记住,方便分辨大小端。

2.2、为什么有大小端?

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

2.3、练习

2.3.1、练习1

请简述大端字节序和小端字节序的概念,设计⼀个小程序来判断当前机器的字节序。(10分)-百度笔试题。
思路一:
创建一个int类型变量 i 赋值成1,如果通过char*解引用也得到1那么就是小端。
//代码1
#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;
}

思路二:

使用联合体方法,创建一个char类型和一个int类型的联合体,将int类型的数据赋值成1,如果char类型的数据也为1,则为小端。

//代码2
int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;
}

2.3.2、练习2

#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;
}

在第十六弹的操作符(下)中我们谈到整型提升,C语言中整型算术运算总是至少以缺省整型类型的精度来进行的。( 即储存数据类型小于整型储存的32比特位时就使小于32比特位的数据类型整型提升) 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型(int),这种转换称为整型提升。

1. 有符号整数提升是按照变量的数据类型的符号位来提升的
2. 无符号整数提升,高位补0

我们可以知道我们一般整数进行计算时需要转化为int类型。

10000000 00000000 00000000 00000001    -1的原码

111111111 111111111 111111111 111111110    -1的反码

111111111 111111111 111111111 111111111    -1的补码

但是a的类型为char类型,因此只能存储8个bit位,即11111111   a在内存中实际存储

b的类型为signed char类型,因此只能存储8个bit位,即11111111   b在内存中实际存储

c的类型为unsigned char类型,因此只能存储8个bit位,即11111111   c在内存中实际存储

a按照%d进行打印,即10进制无符号整数打印,a为char类型,根据整型提升规则,有符号按照符号位提升,a提升之后为11111111 11111111 11111111 11111111

11111111 11111111 11111111 11111111    补码

11111111 11111111 11111111 11111110    反码

1000000 0000000 0000000 00000001   原码    值为-1    因此a打印的值为-1,b同理

c按照%d进行打印,即10进制无符号整数打印,c为unsigned char类型,根据整型提升规则,无符号在前面补0,c提升后为00000000 00000000 00000000 11111111 ----为正数,因为正数的原反补码相同,因此c的10进制值为255

2.3.3、练习3

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

10000000 00000000 00000000 10000000     -128原码

111111111 111111111 111111111 011111111     -128反码

111111111 111111111 111111111 10000000     -128补码

a为char类型,因此a在内存中实际存储为 10000000

a按照%u进行打印,即10进制无符号打印,a首先进行整型提升,无符号按照符号位进行提升,即

11111111 11111111 11111111 10000000    提升之后

按照无符号打印,即直接打印,转化为10进制后结果为:4,294,967,168

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

00000000 00000000 00000000 10000000     128原、反、补码  正数都相等

a为char类型,在内存中存储为10000000

a按照%u打印,先整型提升,char类型按照符号位提升,即

11111111 11111111 11111111 10000000

10进制无符号打印即为4,294,967,168

2.3.4、练习4

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

strlen计算的是'\0'之前的字符串长度,即需知道什么时候为0,循环第一次a[i]=-1-0=-1,然后-2,一直到-128,-128-1为127,然后一直减到0,中间个数有255个,因此长度为255.

2.3.5、练习5

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

根据unsigned char类型大小的取值范围,范围为0-255,因此 i 一定小于等于255,所以此处为死循环,一直打印hello world

#include <stdio.h>
int main()
{unsigned int i;for(i = 9; i >= 0; i--){printf("%u\n",i);}return 0;
}

根据unsigned int类型大小的取值范围,范围为0-4,294,967,295,i 一定大于等于0,因此此处也为死循环,先打印9 8 7 ....0  然后打印最大值,最大值-1.....一直循环。

调试可得下图。

2.3.6、练习6

#include <stdio.h>
int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf("%x,%x", ptr1[-1], *ptr2);return 0;
}

x86环境得到的结果,x64可能会出错。

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

相关文章:

C语言第二十八弹---整数在内存中的存储

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 目录 1、整数在内存中的存储 2、大小端字节序和字节序 2.1、什么是大小端&#xff1f; 2.2、为什么有大小端? 2.3、练习 2.3.1、练习1 2.3.2、练习2 2.…...

java开源xml工具类介绍

在Java中处理XML的常用开源工具有很多&#xff0c;以下是一些流行的库以及简单的示例代码&#xff1a; DOM4J DOM4J 是一个非常流行的Java库&#xff0c;用于处理XML&#xff0c;DOM4J 易于使用&#xff0c;并且提供了很好的性能。 Maven 依赖 …...

Go 语言一些常用语法编写和优化指南

Go 语言以其简洁的语法和强大的并发性能而受到开发者的喜爱。然而&#xff0c;为了充分利用 Go 的潜力&#xff0c;我们需要了解如何优化 Go 程序。本文将介绍一些常见的 Go 语言优化技巧&#xff0c;并通过实际例子进行说明。 推荐系列 来来来,老铁们,男人女人都需要的技术活…...

Golang 语法系列:结构体

结构体&#xff1a;相当于"类" 1.结构体声明 type [name] struct {[field_name] [field_type][field_name] [field_type]... }//例子&#xff1a;type Person struct {name stringage int }其中field_name可以省略 2.结构体的使用 1) 格式1 var person Person p…...

关于iPad中的密码和触控ID的使用,看这篇文章就差不多了

序言 许多苹果iPad型号都有熟悉的密码系统和触控ID,这需要指纹扫描才能解锁设备。本指南向你展示如何使用iPad Air 2或更高版本、iPad Mini 3或更新版本以及iPad Pro设置或更改密码和触控ID指纹。 一些iPad Pro型号支持面部识别,并配备了面容ID而不是触控ID作为安全功能。面…...

Vue3之ref与reactive的基本使用

ref可以创建基本类型、对象类型的响应式数据 reactive只可以创建对象类型的响应式数据 接下来让我为大家介绍一下吧&#xff01; 在Vue3中&#xff0c;我们想让数据变成响应式数据&#xff0c;我们需要借助到ref与reactive 先为大家介绍一下ref如何使用还有什么注意点 我们需…...

wsl内置Ubuntu使用 Dinky 与 Flink 集成

Dinky 与 Flink 集成 说明 本文档介绍 Dinky 与 Flink 集成的使用方法, 如果您是 Dinky 的新用户, 请先阅读 本文档, 以便更好的搭建 Dinky 环境 如果您已经熟悉 Dinky 并已经部署了 Dinky, 请跳过本文档的前置要求部分, 直接阅读 Dinky 与 Flink 集成部分 注意: 本文档基…...

”戏说“ 交换机 与 路由器

一般意义上说 老哥 这文章发表 的 东一榔头 西一锤 呵呵&#xff0c; 想到哪里就啰嗦到哪里 。 交换机&#xff1a; 其实就是在通道交换 路由器&#xff1a; 不光是在通道交换还要在协议上交换 下图你看懂了吗&#xff1f; &#xff08;仅仅数据交换-交换机 协议…...

Linux pageset

1. 引言 在用户进程发生缺页异常时&#xff0c;Linux内核需要分配所需物理页面以及建立也表映射&#xff0c;来维持进程的正常内存使用需求。而对于分配物理页面仅依赖于buddy系统&#xff0c;对于小order页面的分配效率较低。因此Linux通过在每个cpu维护一个page链表&#xff…...

【C++之语法篇003】

C学习笔记---003 C知识开篇1、内联函数1.1、什么是内联函数?1.2、解决外部头文件&#xff0c;重复定义问题1.3、内联函数的总结 2、auto关键字2.1、auto的作用2.2、auto的总结 3、范围for3.1、什么是范围for&#xff1f;3.2、范围for的循环应用 4、指针空值关键字nullptr4.1、…...

Github代码仓库SSH配置流程

作者&#xff1a; Herman Ye Auromix 测试环境&#xff1a; Ubuntu20.04 更新日期&#xff1a; 2024/02/21 注1&#xff1a; Auromix 是一个机器人爱好者开源组织。 注2&#xff1a; 由于笔者水平有限&#xff0c;以下内容可能存在事实性错误。 相关背景 在为Github代码仓库配…...

Arrays工具类的常见方法总结

一、Arrays.asList( ) 1.作用&#xff1a;Arrays.asList( )方法的作用是将数组转换成List&#xff0c;将List中的全部集合对象添加至ArrayList集合中 2.参数&#xff1a;动态参数 (T... a) 3.返回值&#xff1a;List 集合 List<T> 4.举例&#xff1a; package com…...

物联网和人工智能的融合

物联网和人工智能的融合 1. 物联网和人工智能的融合2. 芯片技术的进步3. 安全和隐私保护挑战4. 软件开发和调试技术的创新5. 自动化和智能化趋势 1. 物联网和人工智能的融合 随着物联网和人工智能技术的快速发展&#xff0c;嵌入式系统将更多地与物联网设备和人工智能算法相结…...

【微信小程序】wxss 和 css 、wxml 和 html 区别

wxss 和 css 区别 wxss 支持小程序特有的选择器和 样式属性 scroll-into-view cover-view 等wxss 引入了 rpx 单位&#xff0c;可以根据屏幕宽度进行自适应&#xff0c;使得开发者可以更方便的处理不同尺寸屏幕的适配问题。wxss 背景图片只能引入外链&#xff0c;不能使用本地…...

python统计分析——使用AIC进行模型选择

参考资料&#xff1a;用python动手学统计学 1、导入库 # 导入库 # 用于数值计算的库 import numpy as np import pandas as pd import scipy as sp from scipy import stats # 用于绘图的库 import matplotlib.pyplot as plt import seaborn as sns sns.set() # 用于估计统计…...

Android 11以上获取不到第三方app是否安装

开年第一篇&#xff0c;处理了一下年前的小问题。 问题&#xff1a;本地app跳转到第三方app地图进行导航&#xff0c;获取不到第三方地图是否安装。 解决&#xff1a; 1.添加包名 This can be done by adding a <queries> element in the Android manifest.在app下的…...

Java的编程之旅24——private私有方法

1.private的介绍 在面向对象编程中&#xff0c;private是一种访问修饰符&#xff0c;用于限制成员的访问范围。私有成员只能在所属的类内部访问&#xff0c;对外部的类或对象是不可见的。 private的使用可以带来以下几个好处&#xff1a; 封装实现细节&#xff1a;私有成员可…...

为什么在MOS管开关电路设计中使用三极管容易烧坏?

MOS管作为一种常用的开关元件&#xff0c;具有低导通电阻、高开关速度和低功耗等优点&#xff0c;因此在许多电子设备中广泛应用。然而&#xff0c;在一些特殊情况下&#xff0c;我们需要在MOS管控制电路中加入三极管来实现一些特殊功能。然而&#xff0c;不同于MOS管&#xff…...

CSS的注释:以“ /* ”开头,以“ */ ”结尾

CSS的注释:以“ /* ”开头&#xff0c;以“*/”结尾 CSS的注释: 以“ /* ”开头&#xff0c;以“ */ ”结尾 在CSS中&#xff0c;注释是一种非常重要的工具&#xff0c;它们可以帮助开发者记录代码的功能、用法或其他重要信息。这些信息对于理解代码、维护代码以及与他人合作都…...

MySQL中常见的几种日志类型【重点】

在MySQL中&#xff0c;有几种不同类型的日志&#xff0c;用于记录数据库的活动和操作&#xff0c;以便于故障排查、性能调优和数据恢复等目的。以下是MySQL中常见的几种日志类型&#xff1a; 错误日志&#xff08;Error Log&#xff09;&#xff1a; 错误日志记录了MySQL服务器…...

odoo16-API(Controller)带有验证访问的接口

odoo16-API&#xff08;Controller&#xff09;带有验证访问的接口 目前我使用odoo原生的登录token来验证登陆的有效性 废话不多说直接上代码 # 测试获取session_id import requests class GetOdooData(http.Controller):def getOdooToken(self):# http://localhost:8123访问…...

Eclipse项目间的引用

我们在开发的时候&#xff0c;有时候需要把一个大的项目打散&#xff0c;尤其是现在微服务的架构很流行&#xff0c;一个大的项目往往被拆成很多小的项目&#xff0c;而有的项目作为公共工程被独立出来&#xff0c;比如有个工程专门提供各种Util工具类&#xff0c;有的工程专门…...

matplotlib使用案例3:通过自定义图例类实现图例的任意方向(行 or 列)的排列

这个方法的核心依然是基于matplotlib.legend._get_legend_handles_labels函数。然后将得到的handlers, labels进行重排,使得即使再调用Legend类的绘制方法对图例进行列排列,最终的效果也是图例的行显示,如[1、2、3、4、5、6],当指定ncols=2,Legend类的绘制方法得到的图例如…...

js设计模式:依赖注入模式

作用: 在对象外部完成两个对象的注入绑定等操作 这样可以将代码解耦,方便维护和扩展 vue中使用use注册其他插件就是在外部创建依赖关系的 示例: class App{constructor(appName,appFun){this.appName appNamethis.appFun appFun}}class Phone{constructor(app) {this.nam…...

【性能最佳实践】事务处理和读写策略原来这么关键!

MongoDB针对初级&#xff0c;中级及熟练的技术开发人员推出系列技术文章与行业案例。深入浅出地剖析MongoDB产品基础原理&#xff0c;使用技巧&#xff0c;典型行业场景及应用&#xff0c;还有Code Demo及线上线下活动推荐&#xff01; 欢迎阅读有关MongoDB性能最佳实践的系列…...

【广度优先搜索】【网格】【割点】【 推荐】1263. 推箱子

作者推荐 视频算法专题 涉及知识点 广度优先搜索 网格 割点 并集查找 LeetCode:1263. 推箱子 「推箱子」是一款风靡全球的益智小游戏&#xff0c;玩家需要将箱子推到仓库中的目标位置。 游戏地图用大小为 m x n 的网格 grid 表示&#xff0c;其中每个元素可以是墙、地板或…...

开店怎么做进销存

开设一家店铺&#xff0c;无论是实体店还是网店&#xff0c;进销存管理都是确保店铺正常运营和盈利的关键环节。一款良好的进销存管理软件可以帮助你更好地掌握库存情况、优化采购策略、提高销售效率&#xff0c;并最终实现盈利目标。那么&#xff0c;开店怎么做进销存管理呢&a…...

UE4 C++联网RPC教程笔记(三)(第8~9集)完结

UE4 C联网RPC教程笔记&#xff08;三&#xff09;&#xff08;第8~9集&#xff09;完结 8. exe 后缀实现监听服务器9. C 实现监听服务器 8. exe 后缀实现监听服务器 前面我们通过蓝图节点实现了局域网连接的功能&#xff0c;实际上我们还可以给项目打包后生成的 .exe 文件创建…...

程序员一定要远离“钻研技术无用,搞钱才是正道”的言论

不知道大家有没有刷到过这样的言论&#xff1a; &#xff02;程序员真的不要花大量时间研究底层代码&#xff0c;技术钻研的再高级再牛也逃不过被优化的下场。 前辈们开发一个功能用一天&#xff0c;我开发一个功能得用一个星期&#xff0c;只会显得我像一个技术菜鸟&#xff0…...

el-table同时固定左列和右列时,出现错误情况

最近遇到一个问题,就是需求是要求表格同时固定序号列和操作列,我们用的是饿了么组件库的el-table,如下图,出现了错误情况: 解决方法就是使用doLayout方法: 如果使用了keep-alive,可以在activated里执行doLayout方法: activated() {this.$nextTick(() => {this.$ref…...