moc 发表于 2018-8-18 10:45:25

012-二维数组本质及其做函数参数推演

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

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

        for (i = 0; i < 5; i++)
        {
                //printf("%d\n", (*p));
        }

        // 二维数组
        int a2;
        // a2 --> 数组首元素的地址    --> 一个常量指针   --> 是一个数组指针
        p = a2;

        for (i = 0; i < 3; i++)
        {
                for (j = 0; j < 5; j++)
                {
                        p = i + j;
                        printf("%d\n", p);
                }
        }
        // &a1 和 a2是一样的类型,为了解决步长问题,数组类型的指针+1跳一行数组的大小;数组类型的指针即数组指针
        printf("一维数组&a1: %d   &a1+1 : %d \n", &a1, &a1+1);
        printf("二维数组 a2: %d    a2+1 : %d \n", a2, a2 + 1);

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

void main()
{
        int i, j, tmp = 0;
        int a2;
        int *p = NULL;

        for (i = 0; i < 3; i++)
        {
                for (j = 0; j < 5; j++)
                {
                        a2 = tmp++;
                        //第i行第j列赋值
                        //*(*(a2 + i) + j) 就相当于 tmp++;

                }
        }

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

        system("pause");
}
       
3、数组做函数参数
1、c语言只是只是以机械的值的拷贝方式来传递参数(实参-->形参)
int fun(int a, int b_t)
{
        printf("%d\n%d\n", b_t ,sizeof(a));
}
        原因1:高效
        原因2:C语言在处理a的时候,他只知道&a是多少,没有办法知道n可以为多少,只能把&a传给形参。
                   虽然在形参中 int a, 函数可以得到5这个数字,但 C 并没有这么做,所以写和没写是一样的。
2、数组做函数参数退化问题
        一维数组做函数参数推演:
        int printf1Array(char buf);
int printf1Array(char buf[]);
                int printf1Array(char *buf);
        二维数组做函数参数推演:
                int printf2Array(char buf);
int printf2Array(char buf[]);
int printf2Array(char (*buf));

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

// 把(*ArrayStr)换成ArrayStr或ArrayStr[]是同样的意思,形参时都是数组指针
int printfArray(char (*ArrayStr), int iNum)
{
        int i;
        for (i = 0; i < iNum; i++)
        {
                printf("%s \n", ArrayStr);
        }
        return 0;
}

int sortArrayStr(char myArray, int iNum)
{
        int i = 0, j = 0;
        char buf;
        for (i = 0; i < iNum; i++)
        {
                for (j = i + 1; j<iNum; j++)
                {
                        if (strcmp(myArray, myArray) > 0)
                        {
                                strcpy(buf, myArray);
                                strcpy(myArray, myArray);
                                strcpy(myArray, buf);
                        }
                }
        }
        return 0;
}

int main()
{
        int i = 0, j = 0;
        char buf;   //buf数组名代表数组元素首地址

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

        sortArrayStr(myArray, 4);

        printf("排序之后:\n");
        printfArray(myArray, 4);
        system("pause");
        return 0;
}
4、等价关系
                数组参数                           等效指针参数
      一维数组char a                      指针 char*
       指针数组 char *a            指针的指针 char **a
   二维数组 char a          数组的指针 char(*a)

页: [1]
查看完整版本: 012-二维数组本质及其做函数参数推演