文章目录作者 :ふり
专栏 :C语言进阶
格言 : 知行并进
- 字符指针
- 指针数组
- 数组指针
- 数组的定义
- &数组名VS数组名
- 数组指针的使用
- 数组参数、指针参数
- 一维数组传参
- 二维数组传参
- 一级指针传参
- 二级指针传参
- 结语
本章重点
- 字符指针
- 数组指针
- 指针数组
- 数组传参和指针传参
- 函数指针
- 函数指针数组
- 指向函数指针数组的指针
- 回调函数
- 指针和数组面试题解析
指针的主题,我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:
- 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
- 指针的大小是固定的4/8个字节(32位平台/64位平台)。
- 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。
- 指针的运算。
这个章节,我们继续探讨指针的高级主题。
字符指针
在指针的类型中我们知道有一种指针类型为字符指针 char* ;
#includeint main() { // 写法一 //写法二 const char* p = "abxdef"; //p 里面放的是首字母的地址 ---- a 的地址 //这种 abxdef 属于 常量字符串 ,不可以被改变,所以 我们加入 const 修饰,被改变就报错 printf("%sn", p); return 0; }
❗️❗️❗️ 一道面试题 :
#include 指针数组int main() { char str1[] = "abcdef"; char str2[] = "abcdef"; const char* str3 = "abcdef"; const char* str4 = "abcdef"; if (str1 == str2) //这边比较的是首元素的地址 printf("str1 and str2 are samen"); else printf("str1 and str2 are not samen"); if (str3 == str4) //这里str3和str4指向的是一个同一个常量字符串。 // C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。 // 指向同一个字符串的时候,他们实际会指向同一块内存。 // 但是用相同的常量字符串去初始化 //不同的数组的时候就会开辟出不同的内存块。 //所以str1和str2不同,str3和str4不同。 printf("str3 and str4 are samen"); else printf("str3 and str4 are not samen"); return 0; }
指针数组 - - - 是数组,是用来存放指针的数组
int arr[10]; //整型数组 int int int int int int int int int int char ch[5]; //字符数组 char char char char char //指针数组 int* arr2[6]; //存放整型指针的数组 int* int* int* int* int* int* char* arr3[6]; //存放字符指针的数组 char* char* char* char* char* char*
类似于可以实现二维数组
代码实现:
#include 数组指针的使用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[3] = { arr1,arr2,arr3 }; int i = 0; for (i = 0;i < 3;i++) { int j = 0; for (j = 0;j < 5;j++) { // *(p+i)--> p[i] printf("%d ", *(parr[i] + j)); / return 0; } //数组名通常表示的都是首元素的地址 //但是有2个例外: //1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小 //2. &数组名,这里的数组名表示的依然是整个数组,所以&数组名取出的是整个数组的地址,单位是字节
那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
看代码:
#includeint main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p //int (*)[10] 是数组指针的类型 ---> p2 的类型 //但是我们一般很少这样写代码 int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0;i < sz;i++) { //p是指向数组的, *p 就相当于数组名,就是首元素地址, //加 i 得到地址,解引用获得数组的元素 printf("%d ", *(*p + i)); } return 0; }
一个数组指针的使用:
#includevoid print1(int arr[3][5], int r, int c) { int i = 0; for (i = 0;i < r; i++) { int j = 0; for (j = 0;j < c;j++) { printf("%d ", arr[i][j]); } printf("n"); } } void print2(int(*p)[5], int r, int c) //int(*p)[5] 是首元素地址 { int i = 0; for (i = 0;i < r;i++) { int j = 0; for (j = 0;j < c;j++) { printf("%d ", *((*p + i) + j)); printf("%d ", p[i][j]); // *((*p + i) + j) 和 p[i][j]) 是一个性质 } printf("n"); } } int main() { int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 }; print(arr, 3, 5); print2(arr, 3, 5);//arr表示第一行的地址 // 第一行的地址,是一个一维数组的地址 return 0; }
//int arr[5]; arr是整型数组 //int* parr1[10]; parr1整型指针数组 //int(*parr2)[10]; parr2是数组指针 //int(*parr3[10])[5]; parr3 是存放数组指针的数组 数组参数、指针参数
在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?
一维数组传参
#include 二维数组传参 一级指针传参void test(int arr[])//ok {} void test(int arr[10])//ok {} void test(int* arr)//ok {} void test2(int* arr[20])//ok {} void test2(int** arr)//ok {} int main() { int arr[10] = { 0 }; int* arr2[20] = { 0 }; //数组传参传的是首元素地址 test(arr); test2(arr2); }
#includevoid print(int *p, int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%dn", *(p + i)); } } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9 }; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); //一级指针p,传给函数 print(p, sz); return 0; }
思考:
当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
二级指针传参
#includevoid test(int** ptr) { printf("num = %dn", **ptr); } int main() { int n = 10; int* p = &n; int** pp = &p; test(pp); test(&p); return 0; }
思考:
当函数的参数为二级指针的时候,可以接收什么参数?
结语
今天就介绍到这里指针的其余部分后续继续更新



