【CSAPP】第3章 程序的机器级表示学习笔记4

3.8 数组的分配和访问

1.基本原则

数组分配时会分配一段连续的内存地址,访问时根据该数组元素的大小来使用偏移访问。

例如一个int数组的头指针是x,那么x[3]就是x+3*4,4是int的字节数。

2.指针运算

1)c语言中可以对指针直接进行运算,运算时会根据该指针引用类型的大小进行缩放。

      例如一个指向int的指针++就是将这个指针的地址+4

2)* 和 &运算

*相当于取该指针指向的元素,&相当于取该元素的地址,相当于创建了一个临时指针

3.理解指针和数组

考虑这样一道题,前面的都很简单,主要在于

第一,A1和A2是否会造成null pointer reference,答案是不会的,A1在声明时声明了一个三个int的数组,调用A1就是调用数组的头指针,这个数组已经在内存空间里开辟了,是有实际地址的,所以不会造成null pointer reference,A2是声明了一个int的指针,已经为这个指针申请了大小为8的空间,所以也不会有null pointer reference。

第二,*A1和*A2,首先*A1就是对A1这个地址取他指向的值,而这个值就是A[0],其次,它会导致null pointer reference吗,不会,原因和上面一样。其次*A2,他是对A2这个指针取他指向的值,也就是某个int类型变量,但是在声明这个的时候并没有让他指向某个int值,所以有可能会导致null pointer reference。

上面的比较简单,下面考虑这个题

第一个是一样的,只看**A1,这相当于是拿*A1指向的东西,可是*A1不是指针,他是一个int,所以这个语句都不能通过编译。

第二个要理解是什么,需要理解c语言指针的阅读顺序,从里到外读,先读*A2,声明了一个指针,然后读[3],这是个指针数组,在读int,这是个int型的指针的数组,也就是数组里放了三个指向int的指针,明白了这个就可以看后面的了,*A2就是这个指针数组的头指针也就是A2[0],**A2就是A2[0]这个指针所指向的int型变量。

第三个我目前还没弄明白。

上课还补充了一个,int (*A4[3]),这个跟第二个是一样的。

4.嵌套的数组

有两种嵌套数组,一种是直接声明一个二维数组,a[3][5],那么在访问的时候就会根据定量的行和列偏移来计算位置。第二种是声明三个一维数组,然后在声明一个三个元素的数组,把刚刚声明的三个数组装进去。这样在c语言层面上是一样的,但在机器层面是不一样的,访问时要根据这三个头元素来分别进行偏移访问,不能通过一个头元素来完成所有的偏移。

5.定长数组

在进行定长数组的一些计算时,编译器会进行一些优化,下面的例子很好的展示了这个优化

3.9 异质的数据结构

1.struct

1)struct跟数组很类似,指向结构体的指针会指向这个结构体的第一个字节,然后通过偏移来实现访问。

2)数据对齐的问题

很多机器因为一些硬件层面的原因,比如一次性读固定个字节,那么每个元素的起始地址就必须是这个固定数的倍数,如果不这样可能会产生些别的多余的计算,所以编译器会自动将数据对齐,以提高效率。

考虑下面这个结构体,不用的放置方式会导致占用空间的变化,所以可以以大数据在前的贪心算法来排列结构体,以节省空间。

3)union结构

这个没看明白例子,以后有机会再看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值