• c语言之二级指针


    今天给大家分享一下最近学习到的关于二级指针方面的知识。

    首先说明一下二级指针的三种内存模型,即指针数组,指向指针的指针,二维数组。

    首先来看指针数组,指针数组的定义方式

        //数组 数组中的每一个元素是指针 指针数组
        char *myArray[] = { "aaaa","cccc","bbb","1111" };

    由于[]和*的优先级一致,但是变量是自右向左进行结合的,所以先与[]结合,再与*结合,所以myArray是一个数组,每个数组中存储的char 类型的指针。

    先来看看如何打印该变量。代码如下

    1. void printArray(char **myArray,int num)
    2. {
    3. int i = 0;
    4. for (i = 0;i < num;i++)
    5. {
    6. printf("%s \n", *(myArray + i));
    7. }
    8. }

    利用*取到数组中的首元素的地址,打印出字符串。

    接下来是排序操作,代码如下

    1. void sortMyArray(char **myArray, int num)
    2. {
    3. int i = 0, j = 0;
    4. char *tmp = NULL;
    5. //排序
    6. for (i = 0;i < num;i++)
    7. {
    8. for (j = i;j < num;j++)
    9. {
    10. if (strcmp(myArray[i], myArray[j])>0)
    11. {
    12. //交换的是数组元素,即指针的值
    13. tmp = myArray[i];
    14. myArray[i] = myArray[j];
    15. myArray[j] = tmp;
    16. }
    17. }
    18. }
    19. }

    这边需要注意的是交换元素交换的是指针变量中储存的地址,即指针的指向。

    接下来看一下二维数组的排序操作和打印操作。

    1. #include <stdio.h>
    2. #include <string.h>
    3. #include <stdlib.h>
    4. //打印 排序
    5. //内存越界
    6. //myArray+1和第一种的不一样
    7. //指针的步长不一样,指针所指向的内存空间的数据不一样
    8. void printArray31(char myArray[10][30], int num)
    9. {
    10. int i = 0;
    11. for (i = 0;i < num;i++)
    12. {
    13. printf("%s \n", *(myArray + i));
    14. }
    15. }
    16. void sortMyArray32(char myArray[10][30], int num)
    17. {
    18. int i = 0, j = 0;
    19. char myBuf[30];
    20. for (i = 0;i < num;i++)
    21. {
    22. for (j = i + 1;j < num;j++)
    23. {
    24. //交换的是内存块
    25. if (strcmp(myArray[i], myArray[j])>0)
    26. {
    27. strcpy(myBuf, myArray[i]);
    28. strcpy(myArray[i], myArray[j]);
    29. strcpy(myArray[j], myBuf);
    30. }
    31. }
    32. }
    33. }
    34. int main(int argc, char *argv[])
    35. {
    36. int num = 4;
    37. char myArray[10][30] = { "aaaa","cccc","bbbb","111111111" };
    38. //myArray:编译器只会关心:有10行,每行30
    39. {
    40. int len1 = sizeof(myArray);
    41. int len2 = sizeof(myArray[0]);
    42. int size = len1 / len2;
    43. printf("len1:%d,len2:%d,size:%d\n", len1, len2, size);
    44. }
    45. printf("排序之前\n");
    46. //打印
    47. printArray31(myArray, num);
    48. sortMyArray32(myArray, num);
    49. printf("排序之后\n");
    50. //打印
    51. printArray31(myArray, num);
    52. system("pause");
    53. return 0;
    54. }

    二维数组在进行传参的时候不能利用二级指针来传,主要原因是因为两者之间的步长不一致,在进行排序操作的时候,由于数组名是个常量,所以只能利用内存拷贝的方式来交换值。

    接下来是二级指针

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. char **getMem41(int num)
    5. {
    6. char **p2 = NULL;
    7. int i = 0;
    8. p2 = (char **)malloc(sizeof(char *)*num);
    9. if (p2 == NULL)
    10. {
    11. return p2;
    12. }
    13. for (i = 0;i < num;i++)
    14. {
    15. p2[i] = (char *)malloc(sizeof(char) * 100);
    16. sprintf(p2[i], "%d%d%d", i + 1, i + 1, i + 1);
    17. }
    18. return p2;
    19. }
    20. void printArray41(char **myArray, int num)
    21. {
    22. int i = 0;
    23. for (i = 0;i < num;i++)
    24. {
    25. printf("%s \n", *(myArray + i));
    26. }
    27. }
    28. void sortMyArray41(char **myArray, int num)
    29. {
    30. int i = 0, j = 0;
    31. char *tmp = NULL;
    32. //排序
    33. for (i = 0;i < num;i++)
    34. {
    35. for (j = i;j < num;j++)
    36. {
    37. if (strcmp(myArray[i], myArray[j])<0)
    38. {
    39. //交换的是数组元素,即指针的值
    40. tmp = myArray[i];
    41. myArray[i] = myArray[j];
    42. myArray[j] = tmp;
    43. }
    44. }
    45. }
    46. }
    47. void getMem_Free41(char **p2,int num)
    48. {
    49. int i = 0;
    50. //释放内存
    51. for (i = 0;i < num;i++)
    52. {
    53. if (p2[i] != NULL)
    54. {
    55. free(p2[i]);
    56. p2[i] = NULL;
    57. }
    58. }
    59. if (p2 != NULL)
    60. {
    61. free(p2);
    62. }
    63. }
    64. int main(int argc,char *argv[])
    65. {
    66. int i = 0, j = 0;
    67. char **p2 = NULL;
    68. char *tmp = NULL;
    69. int num = 5;
    70. char tmpbuf[100];
    71. p2 = getMem41(num);
    72. printf("排序之前\n");
    73. printArray41(p2, num);
    74. //排序,交换的是内存
    75. sortMyArray41(p2, num);
    76. //排序,交换的是指针
    77. /*
    78. for (i = 0;i < num;i++)
    79. {
    80. for (j = i + 1;j < num;j++)
    81. {
    82. if (strcmp(p2[i], p2[j])<0)
    83. {
    84. tmp = p2[i];
    85. p2[i] = p2[j];
    86. p2[j] = tmp;
    87. }
    88. }
    89. }
    90. */
    91. printf("排序之后\n");
    92. printArray41(p2, num);
    93. //p2是一个野指针
    94. getMem_Free41(p2, num);
    95. system("pause");
    96. return 0;
    97. }

    接下来看一下这三种模型的内存图

    这边需要注意是当实参是二维数组的时候,形参不能是二级指针,这边做个简单的讲解。

     

    首先来看编译器的提醒。

    “char **”与“char [10][30]”的间接级别不同,说明两者之间的类型是不一致的。

     当运行的时候会发现

     直接出现dump的情况。 

    这时候我们进行调试

     

    我们会发现myArray[0]存储的地址是0x61616161, 而实参数组中myArray[0]中存储的地址明显不是这个值。

    这边做个推演。

    int a[2][3]={1,2,3,4,5,6};

    int **p = a;

    这时候p=&a[0];

    又由于a[0]中存储的又是&a[0][0],所以p=&a[0][0];

    这时候如果直接*p的话就是数字1,再加一个*号的话就是代表1地址中的值,对应之前调试的结果,*myArray的值是0x61616161,这是由于aaaa在内存中的ascii值是97,97的十六进制即是61,一个指针变量的大小是4个字节,如果这样取的话那结果就是取未知内存0x61616161的值,就出现dump的情况。

    这边感谢一下三位大佬提供的资料,附上他们的链接。

    二维数组和指向指针的指针 - Leo.Z - 博客园 (cnblogs.com)

     二维数组和二级指针 - 苏苏苏紫Sue - 博客园 (cnblogs.com)

    为什么不能用二级指针直接指向二维数组_yongheng_1999的博客-CSDN博客

  • 相关阅读:
    系统测试-从研发到测试过程
    告诉大家4个常见的免费备份方法!
    Mysql的常见错误总结
    opencv可视化图片-----c++
    WSL Ubuntu + Docker Desktop搭建python环境
    【DataHub】LinkedIn DataHub学习笔记
    服务架构(微服务体系架构-项目)二.创建阿里云日志存储桶(日志记录-节省服务器及镜像资源,记录日志)
    Docker之部署前后端分离项目(以若依为案例实施必会!!!)
    JavaScript系列之数据类型
    SecureCRT默认使用root用户连接CentOS7
  • 原文地址:https://blog.csdn.net/qq_45526401/article/details/127761150