指针(二)
上次对指针进行了初步认识,接下来,继续挖掘C语言的魂!
指针与一维数组:
这时编译是没有问题的:
编译:
输出结果:
这里面会有点绕,但很重要,先运行一段程序,再来阐述上面的观点:
#include <stdio.h> int main(void) { int a[] = {1, 2, 3, 4, 5}; int* p = a; printf("%p\n", a); printf("%p\n", &a); printf("%p\n", a+1); printf("%p\n", &a+1); return 0; }
运行结果:
结果 a+1 和 &a+1 输出不一样,这时怎么回事呢,且听我慢慢分析:
因为a表示int*,是一个int类型的指针,所以a+1偏移的是一个元素是一个int类型,既4个字节,所以0xbff7f218 + 0x4变成了0xbff7f22c。
而&a表示指向数据变量的指针(数组指针),所以&a+1偏移的一个元素是一个数组int[5]类型,既20个字节: 所以0xbff7f218 + 0x14变成了9xbff2f22c
记住:上面提到了数组指针,下面对其进行一个介绍,注意下面两个区别:
数组指针:
int (*p)[5] 这里的p是一个指针,指向一个具有5个元素的数组指针
指针数组:
int *p[5] 这里的p是一个数组,数组中的元素类型是int*
接着用程序验证一下上面指出的理论:
编译一下,出错了:
再改编一下:
这时编译,则成功了:
注意以下意图表示“数组指针”的方法:
编译:
理解了上面的东西,下面以一个例子,以多种方式来打印数组的元素(理解这段程序的前提,需理解上面所学到的):
#include <stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 5}; int i; int* p; for (i=0; i<5; i++) { printf("a[%d]=%d, *(a+%d)=%d\n", i, a[i], i, *(a+i)); printf("&a[%d]=%p, a+%d=%p\n", i, &a[i], i, a+i); } //以指针的方式打印元素 for (p=a; p<a+5; p++) { printf("address:%p, value:%d\n", p, *p); } return 0; }
输出结果:
指针与二维数组:
这里面比较绕,一一分析来理解:
(回顾)
对于一维数组int a[3];
数组名a可以看成是一个常量指针,类型相当于int*,也就是一个整型指针。
对于二维数组int a[3][4]:
数组名a可以看成是一个常量指针,类型相当于int (*p)[4],也就是数组指针。
而a[2]的类型是int*;a[2] + 2仍然是一个指针。
所以*(a[2] + 2)的类型就是一个int类型。
对于上图中的表示方法有很多,理解性去记性。
下面通过一个例子,来综合使用二维数组的用法:
#include <stdio.h> int main(void) { int a[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} }; int (*p)[3] = a; int i, j; //打印第一行的元素 for (i=0, j=0; j<3; j++) { printf("%d\t", *(*p+j)); } putchar('\n'); //打印第二行的元素 for (i=1, j=0; j<3; j++) { printf("%d\t", *(p[i]+j)); } putchar('\n'); //打印第三行的元素 for (i=2, j=0; j<3; j++) { printf("%d\t", (*(p+i))[j]); } putchar('\n'); //打印第四行的元素 for (i=3, j=0; j<3; j++) { printf("%d\t", *(&p[0][0]+i*3+j)); } putchar('\n'); //打印第四行的元素,变形 for (i=3, j=0; j<3; j++) { printf("%d\t", (&p[0][0])[i*3+j]); } putchar('\n'); return 0; }
运行结果:
为了更好的理解二维数组,下面用程序来分解下:
看运行结果:
也就是:0xbff31ccc + 0xc = 0xbff31cd8
好了,关于指针与数组这一块的内容就学到这,下回继续探索指针!!