四时宝库

程序员的知识宝库

C|二级指针变量与二维数组名之间存在联系并不等同

可以用一个指向数组的指针变量指向一个数组,数组名做右值并被转换为指向数组首元素的指针。

假如有一个n维数组arr:

int arr[i][j][k][…];

其arr的元素类型是:(二维或以上的数组的元素存在长度信息)

int [j][k][…];

也是arr做右值时的类型,可以用一个同类型的指针指向它:(因为数组名常量性质,不能做左值)

int (*ap) [j][k][…] = arr; // 元素与数组存在降一维的关系

这是指针变量与数组名的关系。

而指针变量与数组的关系则更是截然不同,因为前者存储其本身的内存空间只是一个标量的字长大小(sizeof(int)或sizeof(void*)大小),要被初始化后才可以有其指向空间的大小。而arr,当然其本身的大小也是一个指针的字长长度,但其声明即定义,有了指向,其指向的大小是sizeof(arr)或sizeof(int)*i*j*k*…。

关于二级指针,通常其作用有三:

返回一个动态数组;

指针数组与二维指针

己值与他值,新建链表头节点;

具体细节和实例请见:

C|指针变量如何改变其己值、他值(或数组元素而不是数组名)

通常二维数组,通过一个一维的数组指针来处理:

int arr[3][5];

I 一维的数组指针做函数参数,二维的数组名做实参(在此时上下文中数组名被转换为指向一维数组的具有常量性质的指针);

II 一维的数组指针做左值,二维的数组名做实参。

#include <stdio.h>
void useArr(int (*pr)[5],int n){}
int main()
{
    int arr[3][5] = {0};;
    useArr(arr,5);
    int (*pr)[5] = arr;
    return 0;
}

另外,二维指针变量与一维指针数组名,也可以建立等式关系:

    int *parr[5] = {0};
    int **pp = parr; // parr的元素是一个int*

如果要通过函数返回一个二维动态数组(行、列都是变量),可以在函数中使用一个三级指针,看以下实例:

#include <stdio.h>
#include <stdlib.h>
void heapAr(int**p,int n)
{
    *p = (int*)malloc(sizeof(int)*n);
}
void heappa(int*(*p)[5],int n,int m)
{
    for(int i=0;i<n;i++)
    {
        (*p)[i] = (int *)malloc(sizeof(int)*m);
    }
}
void heapArr(int ***p,int r,int c)
{
    *p = (int**)malloc(sizeof(int*)*r);
    for(int i=0;i<r;i++)
    {
        (*p)[i] = (int *)malloc(sizeof(int)*c);
    }
}
int main()
{
    int i,j;
    int *p = NULL;
    int n = 5;
    heapAr(&p,n);
    free(p);
    int * pa[5];
    heappa(&pa,5,5);
    for(i=0;i<5;i++)
        for(j=0;j<5;j++)
            pa[i][j] = (i+1)*(j+1);
    for(i=0;i<5;i++){
        for(int j=0;j<5;j++)
            printf("%d ",pa[i][j]);
        printf("\n");
    }
    for(i=0;i<5;i++)
        free(pa[i]);
    int **pp = NULL;
    int row = 3;
    int col = 5;
    printf("请输入需要分配的数组的行和列:");
    scanf("%d %d",&row,&col);
    heapArr(&pp,row,col);
    for(i=0;i<row;i++)
        for(j=0;j<col;j++)
            pp[i][j] = (i+1)*(j+1);
    for(i=0;i<row;i++){
        for(int j=0;j<col;j++)
            printf("%d ",pp[i][j]);
        printf("\n");
    }
    for(i=0;i<row;i++)
        free(pp[i]);
    free(pp);
    getchar();
    getchar();
    return 0;
}

如果有二级指针返回(而不是通过函数参数列表),则要简洁得多:

#include <stdio.h>
#include <stdlib.h>

int** func2P(int row,int col)
{
    int i,j;
    int**pp = (int**)malloc(sizeof(int*)*row);
    for(i=0;i<row;i++)
        pp[i] = (int*)malloc(sizeof(int)*col);
    for(i=0;i<row;i++)
        for(j=0;j<col;j++)
            pp[i][j] = (i+1)*(j+1);
    return pp;
}

int main()
{
    int row = 3;
    int col = 5;
    int**arr = func2P(row,col);
    for(int i=0;i<row;i++)
    {
        for(int j=0;j<col;j++)
            printf("%2d ",arr[i][j]);
        printf("\n");
    }
    free(arr);
    getchar();
    return 0;
}
/*output:
 1  2  3  4
 2  4  6  8
 3  6  9 12
*/

可以通过数组指针返回一个只有第一维是变量(其它维是常量)的动态数组:

int(*funcArr2D(int row))[COL]  // 返回一个数组指针
{
    int (*buf)[COL];
    buf = (int(*)[COL])malloc(row*COL*sizeof(int)); // malloc(row); ?
    // buf = new int[n][6]; //C++
    for(int i=0;i<row;i++)
        for(int j=0;j<COL;j++)
            buf[i][j] = (i+1)*(j+1);
    return buf;
}

-End-

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接