精华内容
下载资源
问答
  • (*arr)[i]
    (*arr)[i]

     

    展开全文
  • 指针数组、数组指针——用指针访问数组方法总结

    万次阅读 多人点赞 2019-01-14 09:51:11
    目录 1.数组元素的访问 ...2.2.3 指向整个数组的指针(数组指针方式) 3 总结 1.数组元素的访问 数组中的各元素在内存中是连续分布的,要想访问数组中某一元素,那么就必须知道其地址。 在一...

    目录

    1.数组元素的访问

    2.通过指针访问数组

    2.1 通过指针访问一维数组

    2.2 通过指针访问二维数组

    2.2.1 指向元素的指针

    2.2.2 指向每一行的指针(指针数组方式)

    2.2.3 指向整个数组的指针(数组指针方式)

    3 总结


    1.数组元素的访问

           数组中的各元素在内存中是连续分布的,要想访问数组中某一元素,那么就必须知道其地址

           在一维数组中,数组A的元素A[i]的地址&A[i]=A+L*i,其中A为数组的标识符(数组名),也可以用A来代表数组的首地址,L为数组A的数据类型,由此可见,对于一维数组,只需要知道数据类型大小和索引i,就可以知道A[i]的地址,从而就可以访问A[i]了,这也是为什么一维数组的定义可以不指定数组大小,也不会妨碍数组元素的访问

           二维数组,实际上也是一维数组,只不过这个一维数组的每个元素都是一个一维数组。因此,将二维数组的每一行看做一个元素,很容易可以知道二维数组中各元素在内存中是按行优先进行连续存储的,如定义数组A[3][4],那么它在内存中的存储情况如下:

                

            由此也可得到二维数组中元素A[i][j]的地址为&A[i][j]=A+L*(C*i+j),其中A为二维数组A的标识符(数组名),也就是数组的首地址,L为数组元素的数据类型,C为二维数组的列数。由此可见,要知道二维数组中某一元素的地址,就必须知道数据类型大小以及二维数组的列数,这样最终才能实现对二维数组元素的访问,这也是为什么二维数组的定义必须指定列数


    2.通过指针访问数组

           在理解访问数组的指针之前,我们不得不先理解另一个问题:如果定义一个数组A,按前面所说,A就是数组第一个元素的首地址,那么A+1是什么意思呢?我在第一次遇到这个问题的时候,第一反应是A既然表示的是地址,那么A+1自然就是地址+1了呀!然而事实并非如此,我们先来做个测试如图所示:

                                              

           根据测试可知,a+1并非就是a数值上加1,a+2也并非是a数值上加上2,他们实际上两两之间加的是4,即是sizeof(int),而*a=a[0]=1,*(a+1)=a[1]=2.....由此可以知道,a+i实际上就是a的第i个元素的地址,这与前面&A[i]的地址计算是相匹配的。

           而对于二维数组来说,道理其实是一样的,不过二维数组的元素A[0]表示第一行,A[1]表示第二行......因此,二维数组中A是数组的首地址,也就是第0行A[0]的行首地址,A+1就是第1行A[1]的行首地址,.....,A+i就是第i行A[i]的行首地址了....

          

    2.1 通过指针访问一维数组

     一维数组指针的定义方式如下:

    int a[4]={1,2,3,4};
    int *p=a;

           这里定义了一个指针变量p,它指向一个整型变量,而a实际上也就是a的第一个元素a[0]的地址,因此p就指向了数组的第一个元素a[0]。 那么p+1等于什么呢?实际上,p+1在数值上也就等于a+1,因此,p+1其实就是a[1]的地址,p+i就是a[i]的地址,这样,就可以通过*(p+i)来访问a[i]的值了。如图所示:

                                               

          由此可以得出,对于一维数组的数组指针p,数组名p实际上是指向数组第一个元素的指针,即p为int *类型,由于其指向int型数据,因此(p+i)就相当于在p的基础上偏移了i*sizeof(int)的地址大小,就等于数组第i个元素的地址(i=0,1,2....)。

    2.2 通过指针访问二维数组

    2.2.1 指向元素的指针

            这种办法可以说是最直接的办法了,定义方式如下:

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

            在这种定义方式下,对于数组元素的访问就需要一个个元素往后推,结合本文开头所说的,二维数组是按行优先存储的,第i行第j列元素实际上是整个二维数组中的第i*c+j个元素,其中c为二维数组的列数,相对于第一个元素,第i*c+j个元素的地址偏移量为4*(i*c+j),而由于p为int指针,p+x的地址偏移量为p+4*x,因此a[i][j]=*(p+i*c+j)

    2.2.2 指向每一行的指针(指针数组方式)

            这种方式是定义指针来指向二维数组的某一行,定义方式如下:

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

           这里可能会有些迷惑了,为什么这里的指针变量p是指向的a[0]呢?而不能让p指向a呢?

           实际上,前面说过,二维数组实际上是一维数组中每个元素都为一个一维数组,那么此时定义了a[3][4],a代表什么呢?一定要知道,不管数组a是几维的,它实际上都是一维的,a一定是数组第一个元素的地址,这里的第一个元素是指的将n维数组看做一维数组后的第一个元素。因此,在a[3][4]中,将a看做一维数组后它的每一个元素实际上是每一行,因此如果让指针变量p指向a,就相当于让p指向第0行,而这里的第0行并不是整形变量,因此不能让p指向a;

           而如果让p指向a[0],实际上就相当于指向a[0]的第一个元素,也就是a[0][0]了,此时的a[0][0]是整形变量,因此让p指向a[0]是可以的,当然,也可以让p指向a[1]、a[2].....如果让p指向第i行,那么此时的p+j就相当于是一维数组中第j个元素的地址了,即p+j就指向了a[i][j]。

           这样看来,对于有r行的二维数组,就需要定义r个指针指向每一行,这样其实就可以定义一个装有r个指针的数组,其中每一个指针分别指向二维数组的每一行,定义方式如下:

    int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
    int *p[3];
    
    for(int i=0;i<3;i++)p[i]=a[i];

           在这种定义方式下,p[i]即指向数组的第i行,也就是a[i][0],知道了a[i][0]的地址,要想访问a[i][j],地址即是a[i][0]+4*j,这里由于p[i]是int型的指针变量,因此刚好就等于p[i]+j,即a[i][j]=*(p[i]+j)。这就是一种定义指向二维数组的指针的方式,这里的p是以指针作为元素的数组,也就是指针数组

           值得注意的是,这种方法必须知道二维数组的行数

    2.2.3 指向整个数组的指针(数组指针方式)

           这种方式是定义指针来指向整个数组,定义方式如下:

    int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
    int (*p)[4]=a;

           那么这里的p是什么意思呢?如果看不懂(*p)[4],那就把*p用b去替换掉,就成了b[4],这里的b就很明显了,就是一个有4个元素的数组的首地址,那么这里的p的含义也就不难得出了:指向一个有四个元素的数组的首地址,尤其需要注意的是,这里p是指向首地址,并非就是首地址,*p才是首地址,也就是指向第一个元素,因此这里的p也就是指向指针的指针。在int (*p)[4]=a中,p就是指向了第一个含四个元素的数组的首地址,也就是p指向a的首地址也就是a[0],*p指向a[0]的首地址也就是a[0][0],要访问a[0][0],就就是*(*p)了;

           既然p是指向一个有四个元素的数组首地址的指针,那么p+i呢?*p+i呢?要分析清楚这个问题,我们还是参考b[4],前面说过,这里的p是指向首地址的指针,因此p+i就对应了&b+i,因此p+i就指向了&b+i所在的位置;*p是b的首地址,指向b的第一个元素,*p+i就对应了b+i,因此*p+i就指向了b+i所在的位置。

           对于p+i,我们来看看&b+i和&b之间偏移了多少:

                                     

          可以看到,&b+1偏移了16个字节,&b+2偏移了32个字节,而16个字节刚好就是数组b的大小,因此&b+i实际上偏移的地址为i*sizeof(b)=i*c*sizeof(int)。也就是说p+i会跳过整个包含四个整型元素的数组指向下一个包含四个元素的数组,回到a[3][4]中,p指向的是a[0],那么p+1就指向a[1],p+i就指向a[i]了,因此,p+i偏移i个b数组大小的地址,也就是指向二维数组的第i行。

            而对于*p+i,就比较简单了,可以看做*p=b,那么*p+i也就是b+i,即是第i个元素的地址,因此也可得出*p+i指向当前有四个元素的数组的第i个元素

           好了,那么我们要是想访问数组中的a[i][j]怎么办呢?前面说过,要访问数组中的元素,必须先得到其地址,对于a[i][j],它是a数组中第i行的子数组中的第j个元素,综合上面分析的,p+i即指向了数组a的第i行,*(p+i)就是该行的首地址,也就是指向了a[i][0],而对于a[i]这个一维数组的第j个元素当然就是a[i]+j,也就是*(p+i)+j了,因此,a[i][j]的地址就是*(p+i)+j,a[i][j]=*(*(p+i)+j)

    3 总结

          综合以上分析,总结一下用指针访问数组元素的方法(以数组a为例):

     

     

    一维数组a[ ]

                                       二维数组a[R ][ C ]

    定义方式

    T *p=a;

    T *p=&a[m][n];

    T *p[R];

    p[m]=a[m];

    (m=0,1..R-1)

     T (*p)[C]=a;

    访问方式

    a[i]=*(p+i)

    a[i][j]=*(p+(i-m)*C+(j-n))

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

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

     

    展开全文
  • C语言定义数组指针的三种方法

    万次阅读 2015-07-14 22:47:30
    C语言定义数组指针的三种方法C语言中有一种语法叫做数组指针,就是使用一个指针变量指向一个数组,然后对数组进行访问操作. 下面给出代码示例定义的方法, 代码如下:#include<stdio.h>int main(){ //定义数组指针的第...

    C语言定义数组指针的三种方法

    C语言中有一种语法叫做数组指针,就是使用一个指针变量指向一个数组,然后对数组进行访问操作.
    下面给出代码示例定义的方法, 代码如下:

    #include<stdio.h>
    
    int main(){
    
        //定义数组指针的第一种方法
        {
            printf("=====================================\n");
            int (*p)[5] = NULL;
            int arr[5] = {1,2,4,5,7};
            p = &arr;
            int num = sizeof(arr)/sizeof(arr[0]);
            for(int i = 0; i < num; i ++){
                //printf("%d\n",*p[i]);
                //printf("%d\n",p[i]);
                printf("%d\n",(*p)[i]);
    
            }
        }
    
        //定义数组指针的第二种方法
        {
            printf("=====================================\n");
            typedef int (typeArray)[5];
            int arr[5] = {4,6,8,0,1};
    
            typeArray *p = NULL;
            p = &arr;
            int num = sizeof(arr)/sizeof(arr[0]);
            for(int i = 0; i < num;  i++){
                printf("%d\n",(*p)[i]);
            }
    
        }
    
        //定义数组指针的第三种方法
        {
            printf("=====================================\n");
            typedef int (*typeArray)[5];
            int arr[5] = {4,6,8,0,1};
    
            typeArray p = NULL;
            p = &arr;
            int num = sizeof(arr)/sizeof(arr[0]);
            for(int i = 0; i < num;  i++){
                printf("%d\n",(*p)[i]);
            }
        }
    
        return 0;
    }

    我们通过上面的代码可知, 这三种方式通过数组指针来访问数组元素——-(*p)[i]

    如果printf(“%d\n”,p[i]) 那么打印的是数组的首元素地址 ,接下来也是地址—–该数组的首地址加上该数组的长度,………. .例如:该数组的元素首地址是10000那么,接下来的地址是10020, 10040,10060…….
    因为进行了p=&arr的赋值,而&arr代表整个数组的赋值

    那么打印语句printf(“%d\n”,*p[i])打印的是上面所说地址的内容.即10000,10020,10040…… 处的内容

    展开全文
  • a数组名,100表示范围, * 告诉a中存放内容的属性,char 是指定 * 读内存的方法。 sizeof(a) = 100 * 4 = 400; 二维指针 char **a ;//等同于指针数组 a[1]访问第一个存放的指针地址,依此类推。 ...

    指针

    指针的两个重要概念:
    1.分配一个盒子,盒子要有多大?
    在32bit系统中,指针大小为4个字节,2^32种状态(2进制)
    2.盒子里存放的地址,所指向内存的读取方法?
    指针前面的类型就是定义的读取方法。
    在这里插入图片描述
    定义为char *p;一次读取一个字节
    定义为int *p;一次就读4个字节。
    举例如下:

    int main ()
    {
    	int a =0x12345678;
    	int *p1;
    	p1 = &a;
    	printf("the p1 is %x\n",*p1);
    	
    }
    

    输出为 :0x12345678;

    int main ()
    {
    	int a =0x12345678;
    	unsigned char *p1;
    	p1 = &a;//这样写会有警告(某些编译器会直接报错),char型指针指向int型变量,可以在&a前加强制类型转换(char *)
    	printf("the p1 is %x\n",*p1);
    	
    }
    

    输出为:0x12或者0x78(涉及大小端模式问题)

    指针偏移

    int *p;
    p+1,表示访问下一个地址等同于p+sizeof(p[0]);
    地址内容标签访问方式:p[n];和数组访问方式相同

    举例:

    int main()
    {
    	int a = 0x12345678;
    	int b = 0x99991199;
    	
    	int *p1 = &b;
    
    	char *p2 = (char *)&b;
    
    	printf("the p1+1 is %x , %x, %x\n",*(p1+1), p[1], *p1+1);
    
    	printf("the p2 is %x\n", p2[1]);
    }
    

    输出为:the p1+1 is 12345678, 12345678, 9999119a
    the p2+1 is 11(输出结果和编译器有关,可能有的编译器定义变量的空间不连续,就不符合上面所述)。

    多级指针

    二维指针

    int main (int argc , char **argv)
    {
    	int i = 0;
    	while(argv[i] != NULL){
    			printf("the argv is %s\n",argv[i]);
    			i++;
    	}
    }
    

    上述程序在编译后,运行输入./build hello 123 456
    则会打印输出:
    the argv is ./build
    the argv is hello
    the argv is 123
    the argv is 456

    二维指针示意图
    在这里插入图片描述

    指针数组(可以理解为指针的数组)

    普通数组定义
    int a[100]; int代表的是这个空间访问的最小权限

    指针数组定义方式
    char *a[100];a先与右侧[ ]结合
    a数组名,100表示范围, * 告诉a中存放内容的属性,char 是指定 * 读内存的方法。

    sizeof(a) = 100 * 4 = 400;

    二维指针
    char **a ;//等同于指针数组
    a[1]访问第一个存放的指针地址,依此类推。

    数组名的指针保存(数组的指针)

    定义一个指针,指向int a[10];的首地址
    定义一个指针,指向int b[5][6];的首地址

    第一个是一维数组:int *p1 = a;正确

    第二个是二维数组:int **p2 = b;错误
    二维数组与二维指针没有关系

    正确的应该写为 int (*p)[5];

    指针数组和数组指针

    例题1:

    int a[10];
    int *p = a;//数组名为第一个元素地址,也是数组首地址,&a是整个数组的首地址,二者值一样,含义不一样,用法也不一样
    

    以下哪一个表示方法不能表示a[1]:
    A. p+1 B. p++ C.a++ D.a+1
    答案是C,a++等同于a = a+1;数组名是一个常量指针,作为一个常量,自然不能放在=左边进行赋值运算。

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

    千次阅读 2009-10-21 20:53:00
    前几天参加迅雷的笔试遇到了这种题,认真实验了下,代码如下 #include using namespace std; const int row = 2, col = 3;...*(a+row)+col还是一个int *类型指针 所以,*(*(a+row)+col)就是一个int类型的变量了。
  • 从形式 上看多维数组是由多个一维数组组成的,但C语言处理多维数组方法和一维数组一样,都是线性存储,连续分配存储空间,可以用带偏移量(offset)的一 维数组访问多维数组。而在数组规模不确定的情况下,就需要...
  • c语言-数组指针变量

    2018-07-03 10:50:50
    指向数组的指针变量称为数组指针变量。 一个数组是由连续的一块内存单元组成的。 数组名就是这块连续内存单元的首地址。 一个数组也是由各个数组元素(下标变量)组成的。 每个数组元素按其类型不同占用几个连续...
  • 项目中遇到C#调用C++算法库的情况,C++内部运算结果返回矩形坐标数组(事先长度未知且不可预计),下面方法适用于访问C++内部分配的任何结构体类型数组。当时想当然的用ref array[]传递参数,能计算能分配,但是在C#...
  • 通过指针访问二维数组的三种方法

    千次阅读 多人点赞 2019-11-21 17:17:44
    下面总结了一下通过指针访问二维数组的三种方法,里边涉及指针、指针数组、数组指针、指向指针的指针以及二维数组的应用,愿对于大家理解和使用指针有所参考和帮助。 程序如下: #include <stdio.h> int ...
  • 在C语言中,数组操作符[ ]相当于指针取值... 使用ptr[1]或*(p+1)都能访问到a[1]中的数据并且能够修改,在使用中指向数组指针数组名都是相同的,但是它们的初始化方法不同,数组在声明时,表示了需要的大小,比如int
  • #指针访问数组的几种方法 地址法、指针变量法、指针变量下标法 #include<stdio.h> int main() { int a[5], i, * p; p = a; printf("enter five numbers\n"); for(i=0;i<5;i++) { scanf_s("%d", &...
  • 数组异常-空指针异常在使用变量引用一个数组时,变量必须指向一个有效的数组对象,如果该变量的值为null,则意味着没有指向任何数组,此时通过该变量访问数组的元素会出现空指针异常int [] arr = new int[4];...
  • #include void main( ) { int a[5]={23,12,45,33,67},*p=a,i; cout下标方式:"; for (i=0;i;i++) cout[i]; cout; cout指针方式:"; for (p=a;p;p++) cout*p; cout; }对以上
  • 方法1 理解
  • //我实在是找不到什么顺眼的方法,只能以退为进,用一级指针指向二维数组的一级地址#include <stdio.h>int main(void){ int a[5][2]; //int (*b)[5]; //int *(*b)[2]; int *b; b=*a; int i,j; for(i=0;i<5;...
  • 数组指针

    2018-12-02 22:13:53
    对象数组 声明: 类名 数组名[ 元素个数] ; 访问方法: 通过下标访问 数组名[ 下标]. 成员名 指针:一个变量的地址, 指针变量: 用于存放地址的变量 so on.
  • 指针访问数组下标访问 int position; for (vector<int>::iterator iter = cliqueFormationVO.rolePosition.begin(); iter != cliqueFormationVO.rolePosition.end(); iter++) { CCLOG("iter: %d",*...
  • 实例分析用指针访问二维数组的几种方法  之前对数组的概念一直没有理解透彻,只觉得数组名就是个常量指针而已,用法和基本的指针差不多。所以当我尝试用二级指针去访问二维数组时,就经常会出错。下面...
  • 指针的三种访问数组方法

    千次阅读 2018-10-27 18:53:54
    三种之中常用的是*ptr_num(i+1) #include &lt;stdio.h&gt; #include &... //数组名就是首地址,数组就是块连续的内存空间 double num[5]={12,34,66,77,88}; double *ptr_num = num; for(...
  • 前言:在上一篇文章中,笔者介绍了指针数组的内存分配以及初始化,这篇文章来整理下关于数组访问的两种方式。...在使用数组的场合中,我们常见的一种访问方法是使用下标访问数组元素,如:array[...
  • 指针操作数组,方法一是p+index,方法二是p[index],第二种方法跟数组访问方法是一样的。 数组引用返回的是数组的第一个元素的指针地址。 可以将指针指向数组的任意元素,然后从那里开始访问,只要注意不越界就行了...
  • 目前正在做关于UInt8数组的相关应用,遇到问题。 我的代码: @interface MyClass : NSObject { __strong id * myArray; //private byte[] myArray; } @property (nonatomic,readwrite) __strong id * ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,398
精华内容 559
关键字:

数组指针访问方法