5. 指针和数组
指针:
指针变量就是指针变量,不是数组,指针变量的大小是 4/8 个字节,是专门用来存放地址的。
数组:
数组就是数组,不是指针,数组是一块连续的空间,可以存放1个或者多个类型相同的数据。
数组的类型多种多样,int arr[10] 和 int arr[8] 的数组类型就是不一样的,
前者的数组类型是 int [10] , 后者的数组类型是 int [8] )
指针和数组的联系:
1. 数组中,数组名其实是数组首元素的地址,数组名 == 地址 == 指针
2. 当我们知道数组首元素的地址的时候,因为数组又是连续存放的,所以通过这个特性就可以遍历访问数组,数组是可以通过指针来访问的。
回顾:(两种数组名不是首元素地址的情况)
1. sizeof(数组名):数组名单独放在sizeof()内部,这里的数组名表示整个数组,计算的是整个数组的大小
2. &数组名:这里的数组名也表示整个数组,取出的是整个数组的地址
(演示代码:)
#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); int* p = arr; //使用指针变量存放数组首元素地址 for ( i = 0; i < sz; i++) { //打印数组地址 printf("%p == %p\n", p+i, &arr[i]); // 使用指针变量 访问数组地址 == 使用数组下标 访问数组地址 } printf("\n"); for ( i = 0; i < sz; i++) { printf("%d ", *(p + i)); //使用指针访问 数组元素(指针和数组的联系) } return 0; }
6. 二级指针
概念:
二级指针变量就是用来存放一级指针变量的指针变量(例如下图中的pp)
(解引用:二级指针解引用找到一级指针,再对一级指针解引用找到变量内容)
(演示代码:)
#include <stdio.h> int main() { int a = 10; int* p = &a; //p是一级指针变量,指针变量也是变量,变量是在内存中开辟空间的,是变量就有地址 int** pp = &p; //pp就是二级指针变量,二级指针变量就是用来存放一级指针变量的指针变量 *(*pp) = 100; //(*pp):解引用找到p,对p再解引用找到 a //二级指针解引用找到一级指针,一级指针解引用找到变量内容 printf("%d\n", a); return 0; }
二级指针的应用:
(演示代码:涉及到指针数组)
//二级指针引用: #include <stdio.h> int main() { char arr1[] = "abcdef"; char arr2[] = "hello world"; char arr3[] = "cuihua"; //使用 一级指针 存放这三个字符数组的首元素 char* parr[] = { arr1,arr2,arr3 }; //分别存放三个字符数组的首元素地址 //使用 二级指针 存放该一级指针 char** p = parr; //放的是一级指针的首元素地址 return 0; }
7. 指针数组
概念:
指针数组 就是 存放指针 的 数组(本质就是一个数组,只不过存放的是指针)
(演示代码:指针数组存放字符串数组并打印)
//指针数组的应用: #include <stdio.h> int main() { char arr1[] = "abcdef"; char arr2[] = "hello world"; char arr3[] = "cuihua"; //使用 指针数组 存放这三个字符数组的首元素 char* parr[] = { arr1,arr2,arr3 }; //分别存放三个字符数组的首元素地址 //使用 指针数组 循环打印三个首地址,再通过首地址打印三个字符串 int i = 0; for (i = 0; i < 3; i++) { printf("%s\n", parr[i]); // %s:通过字符串首元素地址就可以打印字符串,通过元素地址找到字符串 } return 0; }
(演示代码:指针数组存放整型数组并打印)
//指针数组的应用: #include <stdio.h> int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; //使用 指针数组 存放这三个整型数组的首元素 int* parr[] = { arr1, arr2, arr3 }; //分别存放三个整型数组的首元素地址 //使用 指针数组 循环打印三个首地址,再通过首地址打印三个整型数组 int i = 0; for (i = 0; i < 3; i++) //指针数组大小为3 { //第一个循环:找到指针数组的元素 int j = 0; for (j = 0; j < 5; j++) //整型数组大小为5 { //第二个循环:找到对应数组元素地址后,再通过该地址打印整型数组内容 printf("%d ", parr[i][j]); //也可以写成 *(parr[i] + j) //第一个【】:找到指针数组里的指针,定位到对应整型数组 //第二个【】:定位到对应整型数组后,再用指针访问整型数组元素 } printf("\n"); //打印完一个数组后换行 } return 0; }
总结:
1. 调用指针数组访问里面元素,即指针,找到指针对应的整型数组,其用法类似二维数组的使用方式,即 指针数组名[下标][下标] ,如上图的:parr [i] [j]
2. 指针数组调用整型数组时,用法和二维数组的使用方式类似。但两者有区别,前者的数组元素在内存中是不连续存放的,而后者的数组元素在内存中是连续存放的。原因是:指针数组存放的元素,即指针,来自于不同的整型数组的地址。