HappyCpp

一个不会打代码的程序猿

0%

csapp1

Something interesting but impotant

指针数组与数组指针

Tips:
优先级:()>[]>*;

我们先来看看他们两个有什么区别:

指针数组

指针数组:它是一个数组,前面的指针只是它的修饰语,代表这个数组存储的所有元素都是指针,我们用int *p[n]或者int *(p[n])表示。当p++时,p指向下一个数组元素。我们定义int a[3][4]= {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int *p[3];令p=a会编译错误,这是由于p是指针数组的首地址,而a是二维数组的首地址,地址之间不可以直接赋值,我们可以使用for(int i=0; i<3; i++) { p[i]=a[i]; }使得语句合法。
我们可以借助下图加深理解:

数组指针

数组指针(又称行指针):它是一个指针,这个指针指向了一个一维数组,我们用int (*p)[n]表示。当我们进行p++时,p会跨过n个数据,也可以说p是n的步长。
下面两种方式分别用for和while都可以得到每行的首元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<stdio.h>
#define row 3
#define column 4
int main() {
//array point
int a[row][column]= {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*p)[column];
p=a;

for(int i=0; i<row; i++) {
printf("%d ",*p[i]);
}
printf("\n\n");
int cnt=0;
while(cnt<row) {
printf("%d ",**p);
p++;
cnt1++;
}
return 0;
}
/*
1 5 9

1 5 9
*/

int (*p)[column];这里4是一维数组的长度,如果不等于4,则下面的p=a代码无法执行。
p=a;将二维数组的首地址赋给p,使得指针指向二维数组首地址也就是a[0]或&a[0][0];
p++;p将跨过一行元素到下一行,例如由a[0][]到a[1][]。
我们可以借助下图加深理解:

我们要获取某一元素,可以使用以下几种方法:*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
所以我们可以明白,数组指针只是一个指针变量,只占有一个指针的内存,而指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的内存。

数组与指针

首先看一张图:

PS:
Comp:表示能否成功编译
Bad:是否可能导致空指针引用
Size:sizeof返回值

(以下均为64bit操作系统下的结果)
A1是一个整型数组,里面包含3个整数,所以有3* 4=12字节。
*A1表示取到A1首地址的值,即A1[0],所以为4字节。
A2为指针,所以为8字节。
*A2为一个整数,所以为4字节。
但是*A2可能会导致空指针引用,因为可能没有为整数分配内存。
下图直观的表示了这些情况:

再来看一个更有趣的:

A1是一个整型数组,里面包含3个整数,所以为3* 4=12字节。
*A1表示取到A1首地址的值,即A1[0],是一个整数,所以为4字节。
**A1代表对一个整数间接引用,这是没意义的,所以会编译错误。

A2为指针数组,里面有三个指针,所以有3* 8=24字节。
*A2为取到指针数组首地址,即A2[0],是一个指针,所以为8字节。
**A2表示间接引用的整数,所以为4字节。
**A2可能会导致空指针引用,因为还没有将数组初始化(如果初始化为0,将是数组中的三个非空指针)。

A3是数组指针,是一个指针,所以为8字节。
*A3指向一个含有3个整数的整型数组,所以3* 4=12字节。
*A3指向一个整型数组,只为指针分配内存,但没有为该数组分配内存,没有初始化A3,让它指向一个真正的数组,可能导致空指针引用。
**A3表示间接引用指针指向数组的整数,所以为4字节。
**A3可能导致空指针引用,因为*A3很大可能没有指向一个真正的数组,所以**A3可能找不到指针指向的整数。
下图直观的表示了这些情况: