精华内容
下载资源
问答
  • 1. 二维数组 TYPE array[row][column]; 在定义时row可以不指定,但column必须指定。例如: int arr1[3][2]={{1,2},{3,4},{5,6}};...2.指向二维数组指针: TYPE (*parray)[column]; 在定义时,colu
    1. 二维数组 
    
    TYPE array[row][column];
    在定义时row可以不指定,但column必须指定。例如:
    int arr1[3][2]={{1,2},{3,4},{5,6}};
    等价于:
    int arr1[][2]={{1,2},{3,4},{5,6}};

    2.指向二维数组的指针:
    TYPE     (*parray)[column];
    在定义时,column必须指定,例如定义一个指向上面定义的二维数组的arr1[3][2]的指针:
    int     (*parr1)[2];
    parr1=arr1;

    3.指针数组:
    TYPE     *array[num];
    例如定义一个指针数组,包含三个int的指针:
    int     *parr2[3];
    int a,b,c;
    parr2[0]=&a;
    parr2[1]=&b;
    parr2[2]=&c;

    4.指向二维数组的指针数组:
    TYPE     (*parray[num])[column];
    其中column为二维数组的维度。num为指针的个数,定义时如果直接赋值的话,可以不指定num的大小。
    例如定义一个指针arr1的指针数组,数组的大小为5:
    int     (*parr1[5])[2];
    parr1[0]=arr1;
    printf("%d",parr1[0][2][1]);     // 输出为:6

    另外一个例子:
    static const char _keyboard_lower[4][10]=
    {
         {'q','w','e','r','t','y','u','i','o','p'},
         {'a','s','d','f','g','h','j','k','l'},
         {'z','x','c','v','b','n','m',LITE_KEYSYM_BACKSPACE},
         {LITE_KEYSYM_INPUT_METHOD,LITE_KEYSYM_INPUT_MODE,' ',LITE_KEYSYM_CAPS_LOCK,LITE_KEYSYM_ENTER},
    };
    static const char _keyboard_upper[4][10]=
    {
         {'Q','W','E','R','T','Y','U','I','O','P'},
         {'A','S','D','F','G','H','J','K','L'},
         {'Z','X','C','V','B','N','M',LITE_KEYSYM_BACKSPACE},
         {LITE_KEYSYM_INPUT_METHOD,LITE_KEYSYM_INPUT_MODE,' ',LITE_KEYSYM_CAPS_LOCK,LITE_KEYSYM_ENTER},
    };
    static const char _keyboard_num[4][10]=
    {
         {'1','2','3','4','5','6','7','8','9','0'},
         {'@','$','%','&','*','-','/','(',')'},
         {'!','`',':',';',',','?','.',LITE_KEYSYM_BACKSPACE},
         {LITE_KEYSYM_INPUT_METHOD,LITE_KEYSYM_INPUT_MODE,' ',LITE_KEYSYM_CAPS_LOCK,LITE_KEYSYM_ENTER},
    };

    static const char (*_keyboard_char[])[10]={
         _keyboard_lower,
         _keyboard_upper,
         _keyboard_num,
    };

    展开全文
  • 因此两种的赋值方法在本质上区别不大,但通过查阅资料得知,c++对指针的要求很严格,因此建议如果要用一维指针指向二维数组时候,采用第一种直接强制类型转换的方法比较合法规范,这样会避免出现无可预知的错误!...
    废话少说,先上自己Dev c++上的代码:
       
    #include<stdio.h>
    int main (){
    int c[2][3]={15,2,3,4,5,6}, *p, (*rp)[3],*q,i;
    p = (int*)c;
    rp=c;
    q=c;
    printf ("**rp=%d\n *rp=%p\n c=%p\n p = %p\n q=%p\n *q=%d\n ",**rp,*rp,c,p,q,*q);
    printf("*(rp+1)=%p\n*(p + 1)=%p\n", rp+1,p + 1);
    for(i=0;i<6;i++) {
    printf("*rp[%d]=%d\n",i,*rp[i]);
    }
    printf("\n");
    for(i=0;i<6;i++) {
    printf("q[%d]=%d\n",i,q[i]);
    }
    return 0;
    }
    首先定义一个2*3的二维数组,定义一个一维指针p和q,定义一个指向指针的指针(*rp)[3],问题来了!
    一.将二维数组地址赋给一维指针的问题:
    第一种赋值方法:将二维数组c强制转换成一维的指针类型,并将其赋给一维指针p(代码第4行)
    第二种赋值方法:将二维数组c的地址直接赋给一维指针(代码第6行)
    第一种赋值方法和第二种赋值方法的区别是: 第一种赋值方法可以通过Dev c++的编译,第二种赋值方法不能通过Dev C++的cpp文件编译(会出现error),在后缀名为c 的文件中会出现warning(警告的中文意思是指针类型不匹配),但可以运行!
    两者运行得结果均为

    因此两种的赋值方法在本质上区别不大,但通过查阅资料得知,c++对指针的要求很严格,因此建议如果要用一维指针指向二维数组时候,采用第一种直接强制类型转换的方法比较合法规范,这样会避免出现无可预知的错误!


    二.一维指针和二维指针的偏移地址问题
    在代码的定义类型上,(*rp)[3]表示指向含3个元素的一维整形数组的指针变量,通俗的说法是指向指针的指针,也即是二维指针,为了规范,我用强制类型转换的一维指针p与二维指针rp就偏移地址的问题做一个比较。

    代码第八行:printf("*(rp+1)=%p\n*(p + 1)=%p\n", rp+1,p + 1);
    运行的结果是:

    再与初始定义的地址相比较:


    仔细比较后发现,一维指针和二维指针偏移地址为1时候,一维指针地址偏移了4,二维指针地址偏移了12(指针地址都是以16进制表示)
    原因:二维指针rp的首地址是c[0],一维指针p的首地址是c[0][0],因此rp+1的地址即是c[0]+1==c[1]的地址(这个地址同时也是c[1][0]的地址,p+1的地址即是c[0][0]+1==c[0][1]的地址
    (如果不懂,可以参考一下中山大学2011年软件学院的程序设计理论考试关于指针的一道填空题来理解:
    填空题有一问是: * q + 3 - p=?
    参考答案是6,下面就用上面的分析来解释答案为什么是6
      
    #include <stdio.h>
    int main() {
    int a[3][4]={1,5,8,10,11,3,4,8,7};
    int *p = (int*)a;
    int (*q)[4] = a;
    p += 1;
    q += 1;
    printf("%d\n", *p);
    printf("%d\n", **q);
    printf("%d\n", (*q)[2]);
    printf("%d\n", *q+3-p);
    printf("*q=%p\n", *q);
    printf("p=%p\n", p);
    return 0;
    }

    p是一维指针,初始地址为a[0][0],所以p+1的地址为a[0][1],q是二维指针,初始地址为a[0],所以q+1的地址为a[1][0],
    程序运行后的结果如下


    所以p和q的地址相差3(0x10-0x04=12,12/4=3),再加3即为答案6!
    这就是一维数组和二维数组的地址偏移的大致区别。

    展开全文
  • C语言二维数组指针指向二维数组指针)详解

    千次阅读 多人点赞 2020-05-27 17:43:22
    如有需要,请访问C语言二维数组指针指向二维数组指针)详解 二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例: int a[3][4] = { ...

    声明!本文转载仅为方便学习使用!
    如有需要,请访问
    C语言指针数组(数组每个元素都是指针)详解
    C语言二维数组指针(指向二维数组的指针)详解

    二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例:

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

    从概念上理解,a 的分布像一个矩阵:

    0   1   2   3
    4   5   6   7
    8   9  10  11
    

    但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存:
    二维数组在内存中的存储

    C语言中的二维数组是按行排列的,也就是先存放 a[0] 行,再存放 a[1] 行,最后存放 a[2] 行;每行中的 4 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(3×4) = 48 个字节。

    C语言允许把一个二维数组分解成多个一维数组来处理。对于数组 a,它可以分解成三个一维数组,即 a[0]、a[1]、a[2]。每一个一维数组又包含了 4 个元素,例如 a[0] 包含 a[0][0]、a[0][1]、a[0][2]、a[0][3]

    假设数组 a 中第 0 个元素的地址为 1000,那么每个一维数组的首地址如下图所示
    在这里插入图片描述
    为了更好的理解指针和二维数组的关系,我们先来定义一个指向 a 的指针变量 p:

    int (*p)[4] = a;
    

    括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。

    [ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4])p 就成了一个指针数组,而不是二维数组指针,这在《C语言指针数组》中已经讲到。
    对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [4],那么p+1就前进 4×4 = 16 个字节,p-1就后退 16 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指向二维数组的下一行,p-1会使得指针指向数组的上一行。

    数组名 a 在表达式中也会被转换为和 p 等价的指针!

    下面我们就来探索一下如何使用指针 p 来访问二维数组中的每个元素。按照上面的定义:

    1. p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。

    2. *(p+1)表示取地址上的数据,也就是整个第 1 行数据。注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素,下面的运行结果有力地证明了这一点:

    #include <stdio.h>
    int main(){
        int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
        int (*p)[4] = a;
        printf("%d\n", sizeof(*(p+1)));
        return 0;
    }
    

    运行结果:

    16
    
    1. *(p+1)+1表示第 1 行第 1 个元素的地址。如何理解呢?

    *(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

    1. *(*(p+1)+1)表示第 1 行第 1 个元素的值。很明显,增加一个 * 表示取地址上的数据。

    根据上面的结论,可以很容易推出以下的等价关系:

    a+i == p+i
    a[i] == p[i] == *(a+i) == *(p+i)
    a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)
    

    实例】使用指针遍历二维数组。

    #include <stdio.h>
    int main(){
        int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
        int(*p)[4];
        int i,j;
        p=a;
        for(i=0; i<3; i++){
            for(j=0; j<4; j++) printf("%2d  ",*(*(p+i)+j));
            printf("\n");
        }
        return 0;
    }
    

    运行结果:

    0   1   2   3
     4   5   6   7
     8   9  10  11
    

    指针数组和二维数组指针的区别

    针数组和二维数组指针在定义时非常相似,只是括号的位置不同:

    int *(p1[5]);  //指针数组,可以去掉括号直接写作 int *p1[5];
    int (*p2)[5];  //二维数组指针,不能去掉括号
    

    指针数组和二维数组指针有着本质上的区别:指针数组是一个数组,只是每个元素保存的都是指针,以上面的 p1 为例,在32位环境下它占用 4×5 = 20 个字节的内存。二维数组指针是一个指针,它指向一个二维数组,以上面的 p2 为例,它占用 4 个字节的内存。

    二维数组名做参数传递问题

    展开全文
  • 关于用指针方式访问二维数组的问题 首先说明几种类型: int a[2][4] = { 1,2,3,4,5,6,7,8 };//二维数组 int **p; //二重指针跨度为sizeof(int *) int(*q)[4]; //该语句是定义一个指向数组的指针指向含4个...

    关于用指针方式访问二维数组的问题

    发现二维指针和二维数组很容易被混淆。这里详细梳理一遍
    首先说明几种类型:

    
    int a[2][4] = { 1,2,3,4,5,6,7,8 };//二维数组
    	int **p;	//二重指针,跨度为sizeof(int *)
    	int(*q)[4]; /定义一个指向数组的指针,指向含4个int元素的一维数组。跨度为4*sizeof(int);
    	int * q2[4];	//定义了一个数组 里面存有int * 类型的指针 跨度为sizeof(int *)
    

    关于跨度,他是指针偏移一个单位,其对应的物理地址的偏移量。举个例子:

    int *p =0 //p 指向地址0
    p2=p+1 //p2指向地址4
    

    这里p的跨度为4,因为p增加一位,对应地址增加4位(int 在计算机中占4个字节的存储量)
    每个指针,在机器中他们就是一个数,他的大小都是固定的,但是其不同的类型和跨度完全是编译器阶段赋予他们的含义,比如:

    int a=3
    int *p1=&a;
     float *p2=&a;
    

    他们在存贮在计算机中只是两个数,但是你定义的时候一个使用int,一个使用float,所以编译器认定p1跨度为4,p2跨度为8

    二维数组的在计算机中依然是以一维线性关系排布的
    以二维数组a[2][3]为例,a是由数组a[0]、a[1]组成的一维数组,因此,数组名a可以看作是数组 { a[0], a[1] } 的首地址,即a==&a[0]。然后,对于二维数组,在这里引入两个概念:
    1、一级指针:带一个下标的数组名是一级指针,偏移量是一个元素的长度,它所指对象是数组元素。
    2、二级指针(二重指针):不带下标的数组名是一个逻辑上的二级指针,所指对象是行向量,偏移量是一行元素的存储长度。
    定义一个二维数组和二级指针变量

    int a[2][3],**p;
    

    这里要是想使用p访问二维数组a,不可以用

    p=a;
    

    因为p的定义可以解读为:

    int *(*p);
    

    即指针p的关联类型为int*
    而数组a的定义可以解读为:

     int(a[2])[3];
    

    a是关联类型为int[3]的一维数组。很显然,a与p的关联类型都不一样,故而不能用p去操作a。在这举一个例子来说明:
    如p+i的地址偏移量为
    p+sizeof(int*) *i
    而a+i的地址偏移量为

    a+sizeof(int[4])*i
    

    显然二级指针变量与二维数组名是不同的,我们必须定义一个指向一维数组的指针来操作逻辑上位二级指针的二维数组名。 二维数组的在计算机中的空间类型是以一维线性关系排布的,二维数组的指针使用方式本质上来说属于一维指针的调用方式。但是为了与一维指针相区别,所以必须调用两次*号运算符来接引用。但是二维数组指针与二重指针并不一样。 在未加*号之前 a的跨度为(int的大小列数),在第一次解引用之后*a的跨度为(int 的大小)比如

    a[2][4]**(a+1)+3,**(a+7

    都是对a[2][4]的最后一个元素(第二行第四列)进行访问的操作。
    在这里插入图片描述
    其实※a 和a 指向的地址是一模一样的,只是编译器理解的含义不用,对于a编译器会将其看成是一个指向数组的指针,而*a编译器则会将其看成某一具体数组的首地址。
    *a

    zhong点来了:
    对于使用指针访问2维数组的话,
    ``

    Int a[2][4]={1,2,3,4,5,6,7,8};
     Int **p=(int **)a;
     Cout<< *(*(p+1)+2);
     
    

    这种方法是错误的,不可以使用二维指针直接访问,即使p和a的指向地址相同也不可!
    但是如下方法又是可行的:

     Int a[2][4]={1,2,3,4,5,6,7,8};
     Int **p=(int **)a;
     Cout<< (int (*)[4])p;
     
    

    只要你进行类型转换告诉编译器这是个指向4维数组的指针,编译器就可以正确的解码了。这是为什么呢?,
    上文我说过:二维数组本质上其实是一维指针。所以只能进行一次物理地址的访问。*a和a指向的是一个地址,第一次取*号其实不是真正的去访问物理地址,只不过的编译器看他的方式改变了(对于a编译器会将其看成是一个指向数组的指针,而a编译器则会将其看成某一具体数组的首地址),所以第二次取号才是真正的访问物理地址上数组的元素。
    但是对于二维指针(int **)p来说,这是真正的二维指针,你对它取第一次*号的时候 *p已经真正的访问了物理地址,这时*p是a[2][4]中的第一个元素a[0][0],他的值为1。那么第二次取*的时候,**p就会要求访问的物理地址为1的单元,很明显这是我们的进程不能访问的地址段,所以程序出错。

    展开全文
  • C语言中二维数组二维指针指向指针的数组、指向数组的指针二维数组是形如char a_name[][10]的数组,其中二维数组的第二维必须是一个const(常量),第一维可以不用设置。二维指针是形如char **b_name的指针,意思是...
  • 初学C,碰到一道题,是要求指针数组指向二维数组,并作为函数参数传递,这该如何指向? 请帮忙解答一下指针数组与数组指针两种不同的指向方法,感激不尽。
  • int arr[3][3] 的本质是指向数组的指针即 int (*p)[3],所以二维数组名可以传递给foo( int (*arr)[3]) ,或者foo(int [][3]),但是不能传递给foo(int **arr)  传给函数foo(int **arr) 可以是动态二维数组
  • 二维数组的定义: int **matrix ; -----------见图的操作那篇文章里面的定义 或者这篇文章提供了另外一种方法。 http://c.biancheng.net/view/2022.html 二维数组在概念上是二维的,有行和列,但在内存中...
  • 主要介绍了C语言二维数组指针指向问题,文中不建议用二级指针来访问二维数组,需要的朋友可以参考下
  • 表示这个二维数组由2个一维数组组成 ,每个一维数组由3个 元素组成。 引用方式:1. 数组直接引用 a[1][2] 表示为这个二维数组的第一个一维数组的首元素。也可以用 *(*(a+1)+2) 这样通过指针的方式引用。...
  • 二维数组指针表示,C语言指针引用二维数组详解

    千次阅读 多人点赞 2019-12-09 14:43:53
    指针变量可以指向一维数组中的元素,当然也就可以指向二维数组中的元素。但是在概念和使用方法上,二维数组的指针比一维数组的指针要复杂一些。要理解指针和二维数组的关系首先要记住一句话:二维数组就是一维数组,...
  • 二维数组指针指针数组、数组指针的用法

    万次阅读 多人点赞 2018-03-12 18:16:20
    二维数组指针⑴ 用指针表示二维数组元素。要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题。我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个...
  • 很多公司都问到了二维指针二维数组,以及指向数组的指针的相关问题,在此,简单的给大家总结下,为大家在面试的时候增加一定的信心。 这类题目,总的来说,实际上可以归纳为如下几点: 1、 有一个一维数组int a1...
  • 如果一个指针指向数组,我们就称它为数组指针(Array Pointer) 数组指针指向的是数组中的一个具体元素,而不是整个数组,所以数组指针的类型和数组元素的类型有关。 对指针变量进行加法和减法运算时,是根据...
  • 间接证明二维数组在物理上是线性存储的 #include <stdio.h>// 证明二维数组在物理上是线性存储的 // a[i][j] ...// 定义一个一维指针指向二维数组的时候, 要将其指向二维数组的第一行第一列的地址,也就是
  • 二维数组作为函数形参时,能作为函数实参的是二维数组,数组指针 d.当指针数组作为函数形参时,能作为函数实参的是指针数组,二级指针,一级指针的地址2、实例验证:#include #include <stdl
  • 二维数组指向一个一维数组 √ 二维数组的数组名是二级指针 × 二维数组的数组名是数组指针
  • 指针数组: 是数组元素为指针的数组,本质为数组。...操纵二维数组: int a[i][j]; int (*pa)[j]; pa = a; a :代表该二维数组的首地址 pa :代表该二维数组的首地址 *pa :也代表该二维...
  • 【知识点总结】 1.数组名表示数组的第一个元素的地址。 2.&a(a是一个数组)是数组的...6.二维数组数组名的本质是一个指向一维数组的数组指针 譬如:a[2][3] - -》那么a是二维数组首元素的地址,本质是 int(*ptr)[3
  • 1:数组指针本质上是一个指针,而且是一个指向数组的指针(又称为行指针),在这声明一下数组指针指向二维数组的,对于一维数组数组没有任何意义。指针数组本质是一个数组,它的目的把相同类型的指针统一放在一个...
  •  遇到了一个指针问题:我尝试用一个二维指针指向一个二维数组,发现编译不能通过。 eg: int vis[10][10], int **vis = vis; 问题分析:  后来发现 int** 是指向指针数组的指针,二维数组其实只是一个指针,而二...
  • 对于二维数组的传值,引进了数组指针。 #include void foo(int *p,int n)//一维访问 { for(int i=0;i;i++) printf("%d ",p[i]); printf("\n"); } //因为二维数组的列数必须初始化 void func(int (*p)
  • 指向二维数组指针

    2013-04-09 08:37:56
    主要介绍指向二维数组指针,怎样去使用,定义二维数组。赋值。
  • 首先,我们先介绍一下二维数组二维数组指针二维数组相当于一个特殊的一维数组里面每个元素又是一个一维数组,例如:int a [ 3 ] [3],可以看成一个3行的一个列数组,每一列的元素又是一个长度为3的数组,数组...
  • 二维数组与二维指针(测试环境VS2015)定义一个二维指针指向二维数组应如下定义:int num[4][5]; int (*p)[5]=num;而下面的这种定义在C的编译下是警告(可以成功),但在C++编译下会报错:int num[4][5]; int **p=...
  • 1.指向维数组指针,可以改变指针指向,fangw

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 70,176
精华内容 28,070
关键字:

二维指针指向二维数组