鱼C论坛

 找回密码
 立即注册
查看: 1744|回复: 0

[学习笔记] 012-二维数组本质及其做函数参数推演

[复制链接]
发表于 2018-8-18 10:45:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2018-8-18 13:00 编辑

1、一维数组和二维数组
        int a1[5],内存会分配连续的5*4个字节的内存空间,并把首元素地址(及类型)给a1,(所以a是一个指针,未退化的数组指针)同时&a为该整个数组的地址,其值和a一样,但它是数组数据类型指针,步长为整个数组的大小;
        对于二维数组 int a2[3][5],内存会分配连续的3*5*4个字节的内存空间,其中a2为数组首地址,它是一个二级常量指针,且是一个指向数组类型指针,其步长是数组一行的大小。
        总结:
                int a[5]   一维数组名代表数组首元素的地址,==> a 的类型为 int *
                int b[2][5] 二维数组名同样代表数组首元素的地址,== > b的类型为 int (*)[5]  数组类型的指针,也即数组指针
                数组指针的存在是为了解决线性空间存储下的步长问题。

  1. void main()
  2. {
  3.         // 一维数组
  4.         int i = 0, j = 0;
  5.         int a1[5] = { 3, 4, 5, 12, 2 };
  6.         //直接定义一个数组指针
  7.         int(*p)[5] = &a1;  // &a的步长  5*4 = 20

  8.         for (i = 0; i < 5; i++)
  9.         {
  10.                 //printf("%d\n", (*p)[i]);
  11.         }

  12.         // 二维数组
  13.         int a2[3][5];
  14.         // a2 --> 数组首元素的地址    --> 一个常量指针   --> 是一个数组指针
  15.         p = a2;

  16.         for (i = 0; i < 3; i++)
  17.         {
  18.                 for (j = 0; j < 5; j++)
  19.                 {
  20.                         p[i][j] = i + j;
  21.                         printf("%d\n", p[i][j]);
  22.                 }
  23.         }
  24.         // &a1 和 a2是一样的类型,为了解决步长问题,数组类型的指针+1跳一行数组的大小;数组类型的指针即数组指针
  25.         printf("一维数组&a1: %d   &a1+1 : %d \n", &a1, &a1+1);
  26.         printf("二维数组 a2: %d    a2+1 : %d \n", a2, a2 + 1);

  27.         system("pause");
  28. }
复制代码

2、二维数组存储方式
        不管数组是几维数组,都是线性存储的,数组指针就是为解决步长问题提出来的,数组指针每次跳一行的空间;
        下面我们把数组类型的指针(二级)强制转化为一级指针,来测试二维数组是线性存储的。
  1. int printf2Array(int *p, int num)
  2. {
  3.         int i = 0;
  4.         for (i = 0; i < num; i++)
  5.         {
  6.                 printf("%d ", p[i]);
  7.         }
  8. }

  9. void main()
  10. {
  11.         int i, j, tmp = 0;
  12.         int a2[3][5];
  13.         int *p = NULL;

  14.         for (i = 0; i < 3; i++)
  15.         {
  16.                 for (j = 0; j < 5; j++)
  17.                 {
  18.                         a2[i][j] = tmp++;
  19.                         //第i行第j列赋值
  20.                         //*(*(a2 + i) + j) 就相当于 tmp++;

  21.                 }
  22.         }

  23.         p = (int *)a2;   // 数组指针强制转化为一级指针
  24.         printf2Array(p, 15);  //用转化后的一级指针打印数组

  25.         system("pause");
  26. }
复制代码

       
3、数组做函数参数
1、c语言只是只是以机械的值的拷贝方式来传递参数(实参-->形参)
  1. int fun(int a[5], int b_t)
  2. {
  3.         printf("%d\n%d\n", b_t ,sizeof(a));
  4. }
复制代码

        原因1:高效
        原因2:C语言在处理a[n]的时候,他只知道&a[0]是多少,没有办法知道n可以为多少,只能把&a[0]传给形参。
                   虽然在形参中 int a[5], 函数可以得到5这个数字,但 C 并没有这么做,所以写和没写是一样的。
2、数组做函数参数退化问题
        一维数组做函数参数推演:
  1. int printf1Array(char buf[64]);
  2. int printf1Array(char buf[]);
  3.                 int printf1Array(char *buf);
复制代码

        二维数组做函数参数推演:
       
  1. int printf2Array(char buf[10][30]);
  2. int printf2Array(char buf[][30]);
  3. int printf2Array(char (*buf)[30]);
复制代码


示例程序:
  1. #include "stdlib.h"
  2. #include "stdio.h"
  3. #include "string.h"

  4. // 把(*ArrayStr)[30]换成ArrayStr[10][30]或ArrayStr[][30]是同样的意思,形参时都是数组指针
  5. int printfArray(char (*ArrayStr)[30], int iNum)
  6. {
  7.         int i;
  8.         for (i = 0; i < iNum; i++)
  9.         {
  10.                 printf("%s \n", ArrayStr[i]);
  11.         }
  12.         return 0;
  13. }

  14. int sortArrayStr(char myArray[10][30], int iNum)
  15. {
  16.         int i = 0, j = 0;
  17.         char buf[30];
  18.         for (i = 0; i < iNum; i++)
  19.         {
  20.                 for (j = i + 1; j<iNum; j++)
  21.                 {
  22.                         if (strcmp(myArray[i], myArray[j]) > 0)
  23.                         {
  24.                                 strcpy(buf, myArray[i]);
  25.                                 strcpy(myArray[i], myArray[j]);
  26.                                 strcpy(myArray[j], buf);
  27.                         }
  28.                 }
  29.         }
  30.         return 0;
  31. }

  32. int main()
  33. {
  34.         int i = 0, j = 0;
  35.         char buf[30];   //buf数组名代表数组元素首地址

  36.         // 下面的char *ArrayStr[] = { "ccccc","aaaa", "bbbb", "11111"}(数组指针)内存模型不一样
  37.         char myArray[10][30] = { "cccc", "aaaa", "dddd", "11111" };   
  38.         printf("排序之前:\n");
  39.         printfArray(myArray, 4);

  40.         sortArrayStr(myArray, 4);

  41.         printf("排序之后:\n");
  42.         printfArray(myArray, 4);
  43.         system("pause");
  44.         return 0;
  45. }
复制代码

4、等价关系
                数组参数                           等效指针参数
        一维数组char a[10]                      指针 char*  
       指针数组 char *a[10]              指针的指针 char **a
     二维数组 char a[10][30]          数组的指针 char(*a)[30]

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 10:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表