首页 > 其他分享 >深入理解计算机系统 3.6 数组分配和访问

深入理解计算机系统 3.6 数组分配和访问

时间:2024-10-31 21:19:59浏览次数:3  
标签:计算机系统 指向 数据类型 3.6 地址 引用 数组 指针

C语言中的数组是一种将标量数据聚集成更大数据类型的方式。C语言实现数组的方式非常简单,因此很容易翻译成机器代码。C语言一个不同寻常的特点是可以产生指向数组中元素的指针,并对这些指针进行运算。在机器代码中,这些指针会被翻译成地址计算。

3.6.1 基本原则

对于数据类型T和整型常数N,声明如下:

T A[N];

起始位置表示为工。这个声明有两个效果。首先,它在内存中分配一个L*N字节的连续区域,这里L是数据类型T的大小(单位为字节)。其次,它引人了标识符A,可以用来作为指向数组开头的指针,这个指针的值就是xa。可以用0~N-1的整数索引来访问该数组元素。数组元素i会被存放在地址为工xa+L*i的地方。

3.6.2 指针和引用

‌‌&‌是地址运算符,用于获取变量的地址。当&作用于一个对象上时,它返回该对象的地址。

*‌是解引用运算符,用于通过指针获取指向的值。当*作用于一个指针变量时,它返回指针指向的变量的值。

‌指针和‌引用的主要区别

内存分配‌:

  • 指针‌:指针有自己的内存空间,存储的是某个变量的地址。
  • 引用‌:引用只是一个别名,没有自己的内存空间,直接指向已存在的对象。

初始化‌:

  • 指针‌:可以被初始化为NULL,表示没有指向任何对象。
  • 引用‌:必须在声明时被初始化,并且必须是一个已有对象的引用。

使用方式‌:

  • 指针‌:需要通过解引用操作符*来访问指向的对象。
  • 引用‌:使用时会自动解引用,不需要显式解引用操作。

作为函数参数‌:

  • 指针‌:作为函数参数时,需要对指针进行解引用才能操作对象。
  • 引用‌:作为函数参数时,可以直接对对象进行操作,修改引用所指向的对象。

3.6.3 指针运算

C语言允许对指针进行运算,而计算出来的值会根据该指针引用的数据类型的大小进行伸缩。也就是说,如果p是一个指向类型为T的数据的指针,p的值为x,那么表达式
p+i的值为工十L*i,这里L是数据类型T的大小。

单操作数操作符&和*可以产生指针和问接引用指针。也就是,对于一个表示某个对象的表达式Expr,&Expr是给出该对象地址的一个指针。对于一个表示地址的表达式AExpr,*AExpr给出该地址处的值。因此,表达式Expr与*&Expr是等价的。可以对数组和指针应用数组下标操作。数组引用A[i]等同于表达式*(A+i)。它计算第i个数组元素的地址,然后访问这个内存位置。

扩展一下前面的例子,假设整型数组E的起始地址和整数索引i分别存放在寄存器%rdx和号%rcx中。下面是一些与E有关的表达式。我们还给出了每个表达式的汇编代码实现,结果存放在寄存器%eax(如果是数据)或寄存器%rax(如果是指针)中。

在这些例子中,可以看到返回数组值的操作类型为int,因此涉及4字节操作(例如movl)和寄存器(例如%eax)。那些返回指针的操作类型为int*,因此涉及8字节操作(例如leaq)和寄存器(例如%rax)。最后一个例子表明可以计算同一个数据结构中的两个指针之差,结果的数据类型为1ong,值等于两个地址之差除以该数据类型的大小。

3.6.4 嵌套的数组

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

int A【5】【3】;

等价于下面的声明

typedef int row_t[3];

row3_t A[5];

数据类型row3_t被定义为一个3个整数的数组。数组A包含5个这样的元素,每个元素需要12个字节来存储3个整数。整个数组的大小就是4*5*3=60字节。

标签:计算机系统,指向,数据类型,3.6,地址,引用,数组,指针
From: https://blog.csdn.net/chenwinsagain/article/details/143375863

相关文章

  • 每日算法一练:剑指offer——数组篇(7)
    1.文物朝代确认        展览馆展出来自13个朝代的文物,每排展柜展出5个文物。某排文物的摆放情况记录于数组 places,其中 places[i] 表示处于第 i 位文物的所属朝代编号。其中,编号为0的朝代表示未知朝代。请判断并返回这排文物的所属朝代编号是否能够视为连......
  • 数组排序简介-计数排序(Counting Sort)
    基本思想        通过统计数组中每个元素在数组中出现的次数,根据这些统计信息将数组元素有序的放置到正确位置,从而达到排序的目的。算法步骤计算排序范围:遍历数组,找出待排序序列中最大值元素 nums_max和最小值元素 nums_min,计算出排序范围为 nums_max−nums_min......
  • 数组排序简介-快速排序(Quick Sort)
    基本思想        采用经典的分治策略,选择数组中某个元素作为基准数,通过一趟排序将数组分为独立的两个子数组,一个子数组中所有元素值都比基准数小,另一个子数组中所有元素值都比基准数大。然后再按照同样的方式递归的对两个子数组分别进行快速排序,以达到整个数组有序。......
  • [SCOI2014] 方伯伯的玉米田(树状数组优化 DP)
     loj传送门https://loj.ac/p/2211洛谷题目传送门https://www.luogu.com.cn/problem/P3287解题思路首先,我们可以贪心地思考一下:对于每一次区间的加一操作,右端点是在末尾会比右端点在中间的情况更好。因为,当你的右端点在序列中间的时候,相对之下,后面的数就更小了一些,这样是......
  • 108-二叉树-将有序数组转换为二叉搜索树
    树|二叉搜索树|数组|分治|二叉树二叉搜索树(BinarySearchTree,简称BST)和平衡二叉搜索树(BalancedBinarySearchTree)是计算机科学中非常重要的数据结构,广泛应用于各种算法和系统中。理解它们的定义、特点和性质对于掌握数据结构和算法至关重要。下面,我们将详细......
  • 线段树 & 树状数组
    线段树常用于维护区间值代码和题解有很大差异,但是过了就好voidPushup(intx){ s[x]=(s[x<<1]+s[x<<1|1]);}voidPushdown(intx,intl,intr){ s[x]=(s[x]+ad[x]*(r-l+1)); if(l!=r)ad[x<<1]=(ad[x<<1]+ad[x]); if(l!=r)ad[x<<1|1]=(ad[x<<1|1]+ad[x......
  • DAY48|| 300.最长递增子序列 | 674. 最长连续递增序列 | 718. 最长重复子数组
     300.最长递增子序列300.最长递增子序列-力扣(LeetCode)给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 示例......
  • 总结 JavaScript 中8种数组常用的操作 API,array.push,pop,shift,unshift,slice,splice
    前言JavaScript中数组是一个重要的数据结构,它相比于字符串有更多的方法,在一些算法题中我们经常需要将字符串转化为数组,使用数组里面的API进行操作。本篇文章总结了JavaScript中有许多数组常用的操作API,以下是一些常见的操作及其示例:1.push():在数组末尾添加一个或多个元素,并......
  • leetcode560 和为k的子数组
    leetcode560和为k的子数组packagejava2024_10.day30;importjava.util.HashMap;publicclassleetcode560{/*思路:前缀和+哈希表a[j]-a[i]=k即a[i]=a[j]-k遍历到下标j的时候,先判a[j]==k,相等就ans++,然后查哈希表中a[j]-k的数的个数,然后把a[j]放入哈希......
  • 字符串数组转换为整数数组
    在C#中,可以使用Array.ConvertAll方法来将字符串数组转换为整数数组。classProgram{staticvoidMain(string[]args){//案例1://使用Array.ConvertAll方法将字符串数组转换为整数数组//情况1:当确定每个数值......