Clang Array And Pointer

2016-12-12 10:15:55来源:作者:BeginMan's Blog人点击

layout: post title: “C语言的指针与数组种种关系” category: “c/c++” tags: [sizeof] —

此篇为《C语言点滴》关于指针的总结

一. 指针与数组关系 指针 数组 指针 指针指针 指针数组 数组 数组指针 数组数组

表1 指针与数组的组合

假设以int类型测试:

int **pp 定义了一个指向指针的指针(指针指针) int *pa[5] 定义了一个指针数组 int (*ap)[5] 定义了一个数组指针 int aa[2][3] 定义了一个数组数组,也就是一个二维数组 指针 数组 指针 指针指针: int **pp 指针数组: int *pa[5] 数组 数组指针: int (*ap)[5] 数组数组: int aa[2][3]

表2:四个概念的定义

真理: 指针真理:一个xx 型指针应该指向一个xx 型地址。 数组真理:xx 型数组变量就是一个xx 型地址。 真理推导: 根据真理1可知:一个 指针型 指针指向一个 指针型 地址;一个 数组型 指针指向一个 数组型 地址 根据真理2可知: 指针型 数组变量就是一个 指针型 地址; 数组型 数组变量(二维数组)就是一个 数组型 地址。 综上推导: 一个 指针型指针 可以指向一个 指针型数组变量 , 上表第一行 pp = pa 一个 数组型指针 可以指向一个 数组型数组(二维数组) , 上表第二行 ap = aa 指针变量 数组变量 char 类型 char *p char a[5] 指针类型 int **pp int *pa[5] 数组类型 int (*ap)[5] int aa[2][3]

表3 指针变量可指向对应数组变量

二. 指针指针、指针数组、数组指针 2.1 指针型指针

关于指针型指针,如:

int i = 5;printf("i=%d, &i=%p/n", i, &i);int *p = &i;printf("*p=%d, p=%p, &p=%p/n", *p, p, &p);int **pp = &p;printf("*pp=%d, pp=%p, &pp=%p/n", **pp, pp, &pp);

打印输出:

i=5, &i=0x004f5a6c*p=5, p=0x004f5a6c, &p=0x004f5a5a*pp=5, pp=0x004f5a5a, &pp=0x004f5a4c 每个变量,无论它保存的是什么,它本身也都有地址: 指针变量p 保存的是变量i 的地址0x004f5a6c,但是p 本身的地址是0x004f5a5a。 指针变量pp 中保存的是指针变量p 的地址0x004f5a5a。为了保存指针型变量p 的地址,我们必须定义一个指针型指针,那就是 int **pp

如下图示:

图1:示意图

2.2 指针数组

对于一个指针数组,数组中保存的都是指针,数组名就是指针型地址。为了保存这种指针型地址,根据指针真理,我们自然应该用指针型指针了。

如 int *p[3] ,这是因为 [] 的优先级比 * 号高,所以 int *p[3] 会被编译器解释为 int *(p[3]) 。这就是指针数组

见下:

char *a[] = {"人生苦短", ":grin:", "Python当歌", NULL}; // 指针数组char **p; // 指针指针for (p = a; *p != NULL; p++) { printf("%s/n", *p);}

打印输出:

人生苦短:grin:Python当歌 2.3 数组指针

如何定义一个数组型的指针?不能写成 int *p[3] ,这是因为 [] 的优先级比 * 号高,所以 int *p[3] 会被编译器解释为 int *(p[3]) 。这其实就是上面介绍过的指针数组,而不是我们要定义的数组指针。为了解决这个问题,我们用括号改变它的优先级,写成 int (*p)[3] 。这时 (*p) 是一个指针,指针指向的类型为 int[3] ,这是一个一维数组型变量,符合我们的定义。

图2:对比一维和二维的数组指针实例

有了 int (*p)[3]=array[2][3] 的写法,我们对二维数组也可以利用指针来进行访问了,如下面所示:

p 即 &array[0] 代表二维数组的首地址,第0 行的地址 代表一维int 数组型变量int[]的地址 p+i 即 &array[i] 代表第i 行的地址 一维int 数组型变量int[]的地址 *(p+i) 即 array[i] 代表第i 行第0 列的地址 一维int 数组型int[]变量,等价于int 类型的地址 *(p+i)+j 即 &(array[i][j]) 代表第i 行第j 列的地址 int 类型的地址 *(*(p+i)+j ) 即 array[i][j] 代表第i 行第j 列的元素 int 类型的值”

还是看代码测试吧:

int array[2][3] = { {101, 102, 103}, {201, 202, 203}};int (*p)[3] = array;printf("p=%p, &array[0]=%p/n", p, &array[0]);printf(p == &array[0] ? "true/n" : "false/n");/** out:* p=0x7fff5cfa2540, &array[0]=0x7fff5cfa2540* true*/printf("p+1=%p, &array[1]=%p/n", p+1, &array[1]);printf(p+1 == &array[1] ? "true/n" : "false/n");/** out:* p+1=0x7fff5cfa254c, &array[1]=0x7fff5cfa254c* true*/printf("*(p+1)=%p, array[1]=%p/n", *(p+1), array[1]);printf(*(p+1) == array[1] ? "true/n" : "false/n");/** out:* *(p+1)=0x7fff5cfa254c, array[1]=0x7fff5cfa254c* true*/printf("*(p+1)+2=%p, &(array[1][2])=%p/n", *(p+1)+2, &(array[1][2]));printf(*(p+1)+2 == &(array[1][2]) ? "true/n" : "false/n");/** out:* *(p+1)+2=0x7fff5cfa2554, &(array[1][2])=0x7fff5cfa2554* true*/printf("*(*(p+1)+2)=%d, array[1][2]=%d/n", *(*(p+1)+2), array[1][2]);printf(*(*(p+1)+2) == array[1][2] ? "true/n" : "false/n");/** out:* *(*(p+1)+2)=203, array[1][2]=203* true*/

关键部分就是 优先级 , 如 () > [] > *

下面两篇文章基本搞定:

数组指针和指针数组的区别 指针数组和数组指针

如果还不清楚,就看《深入理解C指针》这本不到200页的书。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台