深入理解计算机系统笔记

news2024/9/17 8:24:22

1.1 嵌套的数组

当我们创建数组的数组时,数组分配和引用的一般原则也是成立的。

例如,声明 int A[5][3];

等价于下面的声明

typedef int row3_t[3];

row3_t A[5]

要访问多维数组的元素,编译器会以数组起始为基地址, (可能需要经过伸缩的)偏移量为索引,产生计算期望的元素的偏移量,然后使用某种 MOV指令。通常来说,对于一个 声明如下的数组:

T D[R][C];

它的数组元素D[i][j]的内存地址为

&D[i][j]= Xd +L(C*i+ j)

这里L是数据类型T以字节为单位的大小。

1.2定长数组

C语言编译器能够优化定长多维数组上的操作代码。这里我们展示优化等级设置为 -01时GCC采用的一些优化。假设我们用如下方式将数据类型fixjnatrix声明为 16X16 的整型数组:

#define N 16;

typedef int fix_matrix[N][N];

这样做的好处是,如果需要修改这个值只需要简单的修改这个# define声明就可以了。

1.3 变长数组

历史上,C语言只支持大小在编译时就能确定的多维数组(对第一维可能有些例外)。 程序员需要变长数组时不得不用malloc或calloc这样的函数为这些数组分配存储空间,而且不得不显式地编码,用行优先索引将多维数组映射到一维数组,ISO C99引入了一种功能,允许数组的维度是表达式,在数组被分配的时候才计算出来。

在变长数组的C版本中,我们可以将一个数组声明如下:

int  A[expr1] [expr2];

它可以作为一个局部变量,也可以作为一个函数的参数,然后在遇到这个声明的时候,通过对表达式和求值来确定数组的维度。

因此,例如要访问 n *n 数组的元素 I ,j,我们可以写一个如下的函数:

int var_ele(long n, int A[n][n], long i, long j){

return A[i][j]; }

参数n必须在参数A[n][n]之前,这样函数就可以在遇到这个数组的时候计算出数组的维度。

GCC为这个引用函数产生的代码如下所示:

int var_ele(long n, int A[n][n], long i, long j)

n in %rdi, A in %rsi, i in %rdx, j in %rcx

1  var_ele:

2  imulq %rdx, %rdi

3  leaq (%rsi,%rdi*4), %rax

4  movl (%rax,%rcx,4), %eax

5  ret

这 个地址的计算类似于定长数组的地址计算,不同点在于

1)由于增加了参数 n, 寄存器的使用变化了;

2)用了乘法指令来计算n * i(第2行),而不是用leaq指令来计算3i 。因此引用变长数组只需要对定长数组做一点儿概括。

动态的版本必须用乘法指令对 i 伸缩n倍,而不能用一系列的移位和加法。在一些处理器中,乘法会招致严重的性能处 罚,但是在这种情况中无可避免。

2.1异质的数据结构

C语言提供了两种将不同类型的对象组合到一起创建数据类型的机制:结构(structure),用关键字 struct 来声明,将多个对象集合到一个单位中;联合(union),用关键 字union 来声明,允许用几种不同的类型来引用一个对象

2.2结构

C语言的struct声明创建一个数据类型,将可能不同类型的对象聚合到一个对象中。 用名字来引用结构的各个组成部分。类似于数组的实现,结构的所有组成部分都存放在内存中一段连续的区域内,而指向结构的指针就是结构第一个字节的地址。编译器维护关于每个结构类型的信息,指示每个字段(field)的字节偏移。它以这些偏移作为内存引用指令中的位移,从而产生对结构元素的引用。

2.3联合

联合提供了一种方式,能够规避C语言的类型系统,允许以多种类型来引用一个对 象。联合声明的语法与结构的语法一样,只不过语义相差比较大。它们是用不同的字段来引用相同的内存块。

考虑下面的声明: struct S3{

char c;

int i[2];

double v;

};

union U3{

char c;

int i[2];

double v; 

};

在一台x86-64Lmux机器上编译时,字段的偏移量、数据类型S3和U3的完整大小如下:

在一些下上文中,联合十分有用。但是,它也能引起一些讨厌的错误,因为它们绕过 了C语言类型系统提供的安全措施。一种应用情况是,我们事先知道对一个数据结构中的两个不同字段的使用是互斥的,那么将这两个字段声明为联合的一部分,而不是结构的一 部分,会减小分配空间的总量。

2.4数据对齐

许多计算机系统对基本数据类型的合法地址做出了一些限制,要求某种类型对象的地 址必须是某个值K(通常是2、4或8)的倍数。这种对齐限制简化了形成处理器和内存系统 之间接口的硬件设计。

例如,假设一个处理器总是从内存中取8个字节,则地址必须为8 的倍数。如果我们能保证将所有的double类型数据的地址对齐成8的倍数,那么就可以 用一个内存操作来读或者写值了。否则,我们可能需要执行两次内存访问,因为对象可能被分放在两个8字节内存块中。

对齐原则是任何K字节的基本对象的地址必须是K•的倍数。可以 看到这条原则会得到如下对齐:

确保每种数据类型都是按照指定方式来组织和分配,即每种类型的对象都满足它的对齐限制,就可保证实施对齐。编译器在汇编代码中放人命令,指明全局数据所需的对齐。

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

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

相关文章

教你快速认识Java中的继承和多态

目录 继承 继承的概念 继承的语法 父类成员访问 在子类方法中或者通过子类对象访问父类成员变量时: 在子类方法中或者通过子类对象访问父类成员方法时: super关键字 子类构造方法: 代码块执行顺序: 多态 多态的实现条件 重写 重…

MySql安全加固:配置不同用户不同账号禁止使用旧密码禁止MySql进程管理员权限

MySql安全加固:配置不同用户不同账号&禁止使用旧密码&禁止MySql进程管理员权限 1.1 检查是否配置不同用户不同账号1.2 检查是否禁止使用旧密码1.3 禁止MySql进程管理员权限 💖The Begin💖点点关注,收藏不迷路&#x1f496…

shell自定义日志输出函数log

Background 在编写比较复杂的脚本时,需要输出相关日志信息,方便知悉脚本的执行情况以及问题的排查。 源码 log.sh # 自定义日志函数 function log(){if [[ $1 "i" || $1 "info" ]]; thenecho -ne "\033[1;34mINFO: \033[0m&…

使用Python操作SQLite数据库

大家好,在数据涌现的今天,数据库已成为生活中不可或缺的工具。Python作为一种流行的编程语言,内置了多种用于操作数据库的库,其中之一就是SQLite。SQLite是一种轻量级的关系型数据库管理系统,它在Python中的应用非常广…

c++异常机制(6) -- 标准库中的异常类

标准程序库异常 我们使用c标准库中的异常类&#xff0c;来实现我们之前文件拷贝的代码。 #include <iostream> #include <stdlib.h> #include <exception> #include <ios>using namespace std;#define BUFFER_SIZE 1024// 将一个文件中的内容拷贝到另…

python中版本,操作系统等问题汇总

1. linux源码部署到windows 1.1ModuleNotFoundError: No module named pwd 这个问题&#xff0c;是因为源码是给linux的。这里在windows中&#xff0c;没有该命令。 解决方法之一&#xff0c;在相应的环境目录中&#xff0c;如图中<MetaGPTenv>虚拟环境中&#xff0c;在…

makefileGDB使用

一、makefile 1、make && makefile makefile带来的好处就是——自动化编译&#xff0c;一旦写好&#xff0c;只需要一个make命令&#xff0c;整个工程完全自动编译&#xff0c;极大的提高了软件开发的效率 下面我们通过如下示例来进一步体会它们的作用&#xff1a; ①…

今日arXiv最热大模型论文:点击即可播放!港中文发布大模型写歌神器!

一首歌&#xff0c;包含作词作曲两个部分。擅长作词or作曲就已经很牛了。比如方文山是周杰伦的御用作词人&#xff0c;而周杰伦写过很多耳熟能详的曲子。而兼具作词作曲才华的全能创作人却是难得一见。 最近港中文发布了一款歌曲创作大模型SongComposer&#xff0c;作词作曲都…

Pegasus智能家居套件样例开发--软定时器

样例简介 此样例将演示如何在Pegasus Wi-Fi IoT智能家居套件上使用cmsis 2.0 接口进行定时器开发。 工程版本 系统版本/API版本&#xff1a;OpenHarmony 3.0 releaseIDE版本&#xff1a;DevEco Device Tool Release 3.0.0.401 快速上手 准备硬件环境 预装windows系统的PC…

uniapp项目申请短信模板临时Nginx配置

现在申请短信模板不允许有变量&#xff0c;且要指向实际业务网站&#xff0c;因为项目是小程序&#xff0c;用uniapp写的&#xff0c;现在申请短信&#xff0c;把uniapp打包成h5项目&#xff0c;上传至服务器&#xff0c;修改niginx配置中springboot项目部分&#xff0c;记录一…

Netty之ChannelHandlerMask详解

Netty的ChannelHandlerMask是用于标记ChannelHandler的位掩码。它被用于指示ChannelHandler的事件处理方式。ChannelHandlerMask 定义了ChannelHandler所有事件。 final class ChannelHandlerMask {static final int MASK_EXCEPTION_CAUGHT 1;static final int MASK_CHANNEL_…

前端src中图片img标签资源的几种写法?

在 Vue 项目中引用图片路径有几种不同的方法&#xff0c;具体取决于你的项目结构和配置。以下是几种常见的方式&#xff1a; 1. 静态资源目录 (Public) 如果你的图片放在了项目的 public 目录下&#xff08;例如&#xff0c;Vite 和 Create Vue App 脚手架工具通常使用这个目…

关于页面置换算法的例题(2)

考虑一个500字的程序的下述逻辑地址访问序列&#xff1a;10&#xff0c;11&#xff0c;104&#xff0c;170&#xff0c;73&#xff0c;309&#xff0c;185&#xff0c;245&#xff0c;246&#xff0c;434&#xff0c;458&#xff0c;364。假定采用页式虚拟内存管理&#xff0c;…

力扣hot100题解(python版41-43题)

41、二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…

理解C#里面的集合有哪些?怎么用,什么是安全集合?

介绍 在C#中&#xff0c;集合是一种用于存储和操作多个元素的数据结构。它们提供了各种操作&#xff0c;如添加、删除、查找等&#xff0c;以及遍历集合中的元素。集合通常根据其实现方式和行为特征进行分类。 集合继承IEnumerable 在C#中&#xff0c;几乎所有的集合类型都实现…

uniapp同步将本地图片转换为base64,支持微信、H5、APP

接上篇&#xff0c;少了一个方法的源代码。 先上代码&#xff1a; ploadFilePromiseSync (url) > { return new Promise((resolve, reject) > { // #ifdef MP-WEIXIN uni.getFileSystemManager().readFile({ filePath: url, encoding: base64, success: res > { let …

TVM 和模型优化的概述(1)

文章目录 1. 从 Tensorflow、PyTorch 或 Onnx 等框架导入模型&#xff08;model&#xff09;。2.翻译成 Relay3. lower 到 张量表达式。4. 使用 auto-tuning 模块 AutoTVM 或 AutoScheduler 搜索最佳 schedule。5. 选择最佳配置进行模型编译。6. lower 到 TIR。7. 编译成机器码…

【JavaScript】面试手撕节流

引入 上篇我们讲了防抖&#xff0c;这篇我们就谈谈防抖的好兄弟 – 节流。这里在老生常谈般的提一下他们两者之间的区别,顺带给读者巩固下。 PS: 开源节流中节流与这个技术上的节流&#xff0c;个人认为本质上是一样的。 开源节流的节流指的是节省公司的金钱开支。前端技术上的…

#stm学习总结 (二十八)硬件随机数实验

28.1 随机数发生器简介 STM32F407 自带了硬件随机数发生器&#xff08;RNG&#xff09;&#xff0c;RNG 处理器是一个以连续模拟噪声为基础的随机数发生器&#xff0c;在主机读数时提供一个 32 位的随机数。 28.1.1 RNG 框图 STM32F407 的随机数发生器&#xff08;RNG&#x…

Python实现双向链表:从基础到应用

一、引言 双向链表是一种比单向链表更复杂的数据结构&#xff0c;每个节点除了包含数据和指向下一个节点的指针外&#xff0c;还包含一个指向前一个节点的指针。这种结构使得我们可以从链表的任何节点开始&#xff0c;向前或向后遍历链表。 目录 一、引言 二、节点定义 三、…