C语言基础之指针3
二级指针和多级指针
二级指针存储的是一级指针的地址
二级指针定义格式
数据类型 * * 指针名
注意:指针数据类型跟指向的空间中数据类型是保持一致的
二级指针的作用:可以操作一级指针记录的地址
#include<stdio.h>
int main() {/*二级指针格式:数据类型 ** 指针名*///定义变量int a = 10;//定义一级指针int* p = &a;//定义二级指针int** pp = &p;return 0;}
#include<stdio.h>
int main() {/*二级指针格式:数据类型 ** 指针名*///定义变量int a = 10;int b = 20;//定义一级指针int* p = &a;//定义二级指针int** pp = &p;//利用二级指针修改一级指针里面记录的内存地址*pp = &b;printf("%p\n", &a);printf("%p\n", &b);printf("%d\n", *p);//20printf("%d\n", **pp);//20return 0;}
数组和指针
数组指针:指向数组的指针叫做数组指针
作用:方便操作数组中的各种数据
#include<stdio.h>int main() {//利用指针遍历数组//定义数组int arr[] = { 10, 20, 30, 40, 50 };int len = sizeof(arr) / sizeof(int);//获取数组的指针,实际上是获取数组的首地址int* p1 = arr;int* p2 = &arr[0];//printf("%p\n", p1); //0000007B88F8F718//printf("%p\n", p2);//0000007B88F8F718//printf("%d\n", *p1);//10//printf("%d\n", *(p1 +1));//20//printf("%d\n", *(p1 +2));//30//printf("%d\n", *(p1 +3));//40/*for (int i = 0; i < len; i++) {printf("%d\n", *p1);p1++;}*/for (int i = 0; i < len; i++) {printf("%d\n", *p1++);}return 0;
}
细节:数组arr参与计算的时候,会退化为第一个元素的指针,但是在这两种情况下不会退化:1.sizeof运算的时候,arr还是整体;2.&arr获取地址的时候,步长:数据类型*数组长度
#include<stdio.h>
int main() {//定义数组int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//sizeof运算的时候,不会退化,arr还是整体printf("%zu\n", sizeof(arr));//40//&arr的时候不会退化,记录的内存地址第一个元素的首地址,也是数组的首地址,步长:数据类型*数组长度//arr参与计算的时候,会退化为第一个元素的指针,记录的内存地址是第一个元素的首地址,也是数组的首地址,步长:数据类型 如:int 4printf("%p\n", arr);printf("%p\n", &arr);printf("%p\n", arr + 1);printf("%p\n", &arr + 1);//运行结果://000000EF764FFA08// 000000EF764FFA08// 000000EF764FFA0C// 000000EF764FFA30return 0;
}
二维数组
概念:把多个小数组,放到一个大的数组中去
定义格式:
数据类型 arr[m][n] = {{1,2,3,4....},{1,2,3,4....},{1,2,3,4....}}
m:二维数组的长度n:一维数组的长度
举例并遍历数组
#include<stdio.h>
int main() {//定义一个二位数组//1./*int arr[3][5] ={{1,2,3,4,5},{11,22,33,44,55},{111,222,333,444,555}};*///利用索引的方式进行遍历// //1.//arr[0]:表示二维数组当中的第一个一维数组//arr[1]:表示二维数组当中的第二个一维数组//arr[2]:表示二维数组当中的第三个一维数组/*for (int i = 0; i < 3; i++) {for (int j = 0; j < 5; j++) {printf("%d ", arr[i][j]);}printf("\n");}*///2.int arr1[3] = { 1,2,3 };int arr2[5] = { 11,22,33,44,55 };int arr3[9] = { 1,2,3,4,5,6,7,8,9 };//把三个一维数组放入到二位数组当中// 数组的数据类型跟内部存储的元素保持一致int* arr[3] = { arr1, arr2, arr3 };int len1 = sizeof(arr1) / sizeof(int);int len2 = sizeof(arr2) / sizeof(int);int len3 = sizeof(arr3) / sizeof(int);int lenArr[3] = { len1, len2, len3 };for (int i = 0; i < 3; i++) {for (int j = 0; j < lenArr[i]; j++) {printf("%d ", arr[i][j]);}printf("\n");}return 0;
}
注意:上面第二个代码内层循环中不能写成这样
int len = sizeof(arr[i])/sizeof(int);
for(int j = 0; j < len; j++){
...}
因为sizeof(arr[i])得到的是指针的大小(在64位系统中通常是8个字节)
二维数组(指针操作)
数组指针:指向数组的指针
int * p = arr;步长:int (4个字节)
int (*p)[5] = &arr;步长:int * 5
#include<stdio.h>
int main() {//二维数组//利用指针遍历二维数组//定义一个二维数组int arr[3][5] = {{1,2,3,4,5},{11,22,33,44,55},{111,222,333,444,555},};//利用指针遍历二维数组//数组指针的数据类型:要跟数组内部元素的数据类型保持一致//二维数组里面存储的是一维数组int[5]int (*p)[5] = arr;//p指向包含5个整数的数组的指针printf("%p\n", arr);printf("%p\n", arr+1);//相差20个字节for (int i = 0; i < 3; i++) {//遍历一维数组for (int j = 0; j < 5; j++) {printf("%d ", *(*p + j));}printf("\n");p++;}
}
指针数组:存放指针的数组
#include<stdio.h>
int main() {//定义三个一维数组int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 11,22,33,44,55 };int arr3[5] = { 111,222,333,444,555 };//把三个一维数组的内存地址放入二维数组当中int* arr[3] = { arr1,arr2,arr3 };//获取指针int** p = arr;//p 存放的是 arr 数组的首地址//遍历数组for (int i = 0; i < 3; i++) {for (int j = 0; j < 5; j++) {printf("%d ", *(*p + j));}printf("\n");p++;}return 0;
}