zoukankan      html  css  js  c++  java
  • C语言-第26课

    第26课 - 多维数组和多维指针

     

     

    1. 指向指针的指针

    1指针变量的本质是一个变量,在内存中会占用一定的空间,因此可以定义指针来保持指针变量的地址值。

    2定义指向指针的指针,主要由于指针也同样存在传值调用与传址调用。

    eg:

    #include<stdio.h>

    #include<string.h>

    int main()

    {

    int a = 5;

    int* p = NULL;

    int* k = NULL;

    k = &a;

    int** pp = NULL;  //指向指针的指针

    pp = &p;   //pp指向的是一级指针的地址

    *pp = &a;  //通过*这个钥匙,大考pp这个防盗门,得到的是*p,将a的地址赋值给*//p,也就是指针p指向a

    printf("%d,%d,%d,%d ",a,*p,**pp,*k);

    return 0;

    }

    运行结果:5555

    注:为什么需要指向指针的指针

    l 指针的本质也是变量

    l 对于指针同样存在传值调用与传址调用

    实例分析---多级指针的分析与使用,重置动态空间大小

    正常情况下,我们为p在堆上申请了5个空间,但是,在实际的应用中,我们要用的空间,可能大于5,也可能小于5,所以需要重新分配地址空间,我们就编辑这样的一个函数来实现这一个功能。

    #include <stdio.h>

    #include <malloc.h>

    int reset(char**p, int size, int new_size)  //第一个参数,是一个指向指针的指针。

    {

        int ret = 1;

        int i = 0;

        int len = 0;

        char* pt = NULL;

        char* tmp = NULL;

        char* pp = *p;

        if( (p != NULL) && (new_size > 0) )

        {

            pt = (char*)malloc(new_size);    

            tmp = pt;

            len = (size < new_size) ? size : new_size;

    //取新旧地址中最短的

            for(i=0; i<len; i++)

            {

                *tmp++ = *pp++;      

            }

            free(*p);

            *p = pt;

        }

        else

        {

            ret = 0;

        }

        return ret;

    }

    int main()

    {

        char* p = (char*)malloc(5);   //在堆空间上申请5个空间

        printf("%0X ", p);

        //我们通过函数改变的是函数外面的一个函数的值,所以我们要进行的是传址操作。

        if( reset(&p, 5, 3) )

        {

            printf("%0X ", p);

        }

        return 0;

    }

    1. 二维数组

    1二维数组名在内存中以一维的方式排布。

    2二维数组中的第一维是一维数组。

    3二维数组中的第二维才是具体的值。

    4)二维数组的组名可以看做常量指针。

    例程--以一维的方式遍历二维数组

    #include <stdio.h>

    #include <malloc.h>

    void printArray(int a[], int size)

    {

        int i = 0;  

        printf("printArray: %d ", sizeof(a));

        for(i=0; i<size; i++)

        {

            printf("%d ", a[i]);

        }

    }

    int main()

    {

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

        int* p = &a[0][0];    //指针指向的地址

        printArray(p, 9);

        return 0;

    }

    运行结果:

    printArray: 4

    0

    1

    2

    3

    4

    5

    6

    7

    8

    分析:我们发现二维数组可以用一维的方式打印出来,说明二维数组在物理的存储上是以一维也就是线性的方式排布的

    下面再分析一个问题:int matrix[2][4];  matrix到底是24列,还是42列?

    答:是两行四列。

    1. 数组名

    (1)一维数组名代表数组首元素的地址。

    int a[5]    a的类型是int*

    (2)二维数组名同样代表数组首元素的地址

    int m[2][5]   m的类型是int(*)[5],即数组指针

    二维数组可以看做一维数组,二维数组中的每个元素都是同类型的一维数组,,此时将二维数组看作一维数组。上面m的类型是数组指针。有如下的例程:

    #include <stdio.h>

    int main()

    {

        int a[5][5];

        int(*p)[4];

        p = a; //指针指向一维数组,也就是大门对应大门。

        printf("%d ", &p[4][2] - &a[4][2]);

    }

    运行结果:-4

    分析:

    首先我们知道指针数组p和二维数a的类型是不符合的。安一维数组的排列方式,发现&a[4][2](指向第22个元素)超前&p[4][2](指向第18个元素)四位。因为a[]一组you5个元素,*p一组只有4个元素。

    或者这样想,p[4]就是p+4*sizeof(p),它的值是16a[4就是a+4*sizeof(a)它的值是20。下面它们同样是再偏移两个,一样的。相差4.

    下面我们看另一个例子--以指针的方式遍历2维数组:

    #include <stdio.h>

    int main(int argc, char* argv[], char* env[])

    {

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

        int i = 0;

        int j = 0;

        for(i=0; i<3; i++)

        {

            for(j=0; j<3; j++)

            {

                printf("%d ", *(*(a+i) + j));  //等价于a[i][j]

            }

        }

    printf(" ");

    }

    运行结果:0 1 2 3 4 5 6 7 8

    手把手写代码---如何动态申请二维数组,以二维指针来模拟

    #include<stdio.h>

    #include<malloc.h>   //动态申请,必须要有而定头文件

    int** malloc(int row, int col)

    {

    int** ret = (int**)malloc(sizeof(int**)*row);

    int* p = (int*)malloc(sizeof(int)*row*col);

    int i = 0;

    if(ret&&p)

    {

    for(i=0; i<row;i++)

    {

    ret[i] = (p + i*col);

    }

    }

    else

    {

    free(ret);

    free(p);

    ret = NULL;

    }

    return ret;

    }

    void free2d(int** a)

    {

    free(a[0]);

    free(a);

    }

    int main()

    {

    return 0;

    }

    数组小结

    1C语言中只有一维数组,而且数组大小必须在编译期就作常数确定。

    2C语言中一维数组的元素可以是任何类型的数据,包括可以是另一个数组。

    3C语言中只有数组的大小和数组首元素的地址是编译器直接确定的。

  • 相关阅读:
    HNOI 2006 BZOJ 1195 最短母串
    BZOJ 3029 守卫者的挑战
    Codeforces 401D Roman and Numbers
    ZJOI2010 数字计数
    BZOJ 3329 Xorequ
    Codeforces 235 C
    SPOJ 8222 Substrings
    BZOJ 1396 识别子串
    (模板)归并排序
    poj3122 Pie (二分)
  • 原文地址:https://www.cnblogs.com/free-1122/p/9783854.html
Copyright © 2011-2022 走看看