1. 二级指针基本概念

这里让我们花点时间来看一个例子,揭开这个即将开始的序幕。考虑下面这些声明:

  1. int a = 12;
  2. int *b = &a;

它们如下图进行内存分配:
image.png

假定我们又有了第3个变量,名叫c,并用下面这条语句对它进行初始化:

  1. c = &b;

它在内存中的大概模样大致如下:
image.png

问题是:c的类型是什么?
显然它是一个指针,但它所指向的是什么?变量b是一个“指向整型的指针”,所以任何指向b的类型必须是指向“指向整型的指针”的指针,更通俗地说,是一个指针的指针。
它合法吗?是的!指针变量和其他变量一样,占据内存中某个特定的位置,所以用&操作符取得它的地址是合法的。那么这个变量的声明是怎样的声明的呢?

那么这个**c如何理解呢?*操作符具有从右想做的结合性,所以这个表达式相当于*(*c),我们从里向外逐层求职。*c访问c所指向的位置,我们知道这是变量b.第二个间接访问操作符访问这个位置所指向的地址,也就是变量a.指针的指针并不难懂,只需要留心所有的箭头,如果表达式中出现了间接访问操作符,你就要随箭头访问它所指向的位置。

2 二级指针做形参输出特性

二级指针做参数的输出特性是指由被调函数分配内存

  1. //被调函数,由参数n确定分配多少个元素内存
  2. void allocate_space(int **arr,int n){
  3. //堆上分配n个int类型元素内存
  4. int *temp = (int *)malloc(sizeof(int)* n);
  5. if (NULL == temp){
  6. return;
  7. }
  8. //给内存初始化值
  9. int *pTemp = temp;
  10. for (int i = 0; i < n;i ++){
  11. //temp[i] = i + 100;
  12. *pTemp = i + 100;
  13. pTemp++;
  14. }
  15. //指针间接赋值
  16. *arr = temp;
  17. }
  18. //打印数组
  19. void print_array(int *arr,int n){
  20. for (int i = 0; i < n;i ++){
  21. printf("%d ",arr[i]);
  22. }
  23. printf("\n");
  24. }
  25. //二级指针输出特性(由被调函数分配内存)
  26. void test(){
  27. int *arr = NULL;
  28. int n = 10;
  29. //给arr指针间接赋值
  30. allocate_space(&arr,n);
  31. //输出arr指向数组的内存
  32. print_array(arr, n);
  33. //释放arr所指向内存空间的值
  34. if (arr != NULL){
  35. free(arr);
  36. arr = NULL;
  37. }
  38. }

3. 二级指针做形参输入特性

二级指针做形参输入特性是指由主调函数分配内存

  1. //打印数组
  2. void print_array(int **arr,int n){
  3. for (int i = 0; i < n;i ++){
  4. printf("%d ",*(arr[i]));
  5. }
  6. printf("\n");
  7. }
  8. //二级指针输入特性(由主调函数分配内存)
  9. void test(){
  10. int a1 = 10;
  11. int a2 = 20;
  12. int a3 = 30;
  13. int a4 = 40;
  14. int a5 = 50;
  15. int n = 5;
  16. int** arr = (int **)malloc(sizeof(int *) * n);
  17. arr[0] = &a1;
  18. arr[1] = &a2;
  19. arr[2] = &a3;
  20. arr[3] = &a4;
  21. arr[4] = &a5;
  22. print_array(arr,n);
  23. free(arr);
  24. arr = NULL;
  25. }

4. 强化训练_画出内存模型图

  1. void mian()
  2. {
  3. //栈区指针数组
  4. char *p1[] = { "aaaaa", "bbbbb", "ccccc" };
  5. //堆区指针数组
  6. char **p3 = (char **)malloc(3 * sizeof(char *)); //char *array[3];
  7. int i = 0;
  8. for (i = 0; i < 3; i++)
  9. {
  10. p3[i] = (char *)malloc(10 * sizeof(char)); //char buf[10]
  11. sprintf(p3[i], "%d%d%d", i, i, i);
  12. }
  13. }

5. 多级指针

  1. //分配内存
  2. void allocate_memory(char*** p, int n){
  3. if (n < 0){
  4. return;
  5. }
  6. char** temp = (char**)malloc(sizeof(char*)* n);
  7. if (temp == NULL){
  8. return;
  9. }
  10. //分别给每一个指针malloc分配内存
  11. for (int i = 0; i < n; i++){
  12. temp[i] = malloc(sizeof(char)* 30);
  13. sprintf(temp[i], "%2d_hello world!", i + 1);
  14. }
  15. *p = temp;
  16. }
  17. //打印数组
  18. void array_print(char** arr, int len){
  19. for (int i = 0; i < len; i++){
  20. printf("%s\n", arr[i]);
  21. }
  22. printf("----------------------\n");
  23. }
  24. //释放内存
  25. void free_memory(char*** buf, int len){
  26. if (buf == NULL){
  27. return;
  28. }
  29. char** temp = *buf;
  30. for (int i = 0; i < len; i++){
  31. free(temp[i]);
  32. temp[i] = NULL;
  33. }
  34. free(temp);
  35. }
  36. void test(){
  37. int n = 10;
  38. char** p = NULL;
  39. allocate_memory(&p, n);
  40. //打印数组
  41. array_print(p, n);
  42. //释放内存
  43. free_memory(&p, n);
  44. }