精华内容
下载资源
问答
  • 2021-02-18 20:50:59

    所谓数组的指针,即指数组的起始地址,数组元素的指针是指数组元素的地址。
    1.一维数组的地址

    在C语言中,数组名是个不占内存的地址常量,它代表整个数组的存储首地址。
    一维数组元素a[i]的地址可以写成表达式&a[i]或a+i,&a[i]是用下标形式表示的地址,a+i是用指针形式表示的地址,二者结果相同。元素a[i]的地址等于数组首地址向后偏移若干字节,偏移的字节数等于a[i]与首地址之间间隔元素的数目乘以一个元素所占存储单元的字节数。
    那么,*(a+i)表示a+i地址中的内容,就是a[i]的值,这就是通过地址常量数组名引用一维数组。
    2.一维数组指针的定义
    定义一个指向数组的指针变量的方法,与定义指向简单变量的指针变量的方法相同。例如:
    int a[10]={1,2,3,4,5,6,7,8,9,10}; /定义a为包含10个整型数据的数组/
    int *p; /定义p为指向整型变量的指针变量/
    定义了一个整型数组a和一个指向整型变量的指针变量p。这时指针变量p并没有指向任何对象,只有当数组a的起始地址赋值给指针变量p时,指针p才表示指向数组a,称指针p为指向数组a的指针。指向过程可以通过下面两种方法实现:
    (1)用数组名做首地址。形式为:
    p=a;
    表示将数组a的起始地址赋值给指针p,而不是将数组a的所有元素赋值给指针p。

    数组a的起始地址赋值给指针,也可以在指针定义的同时进行。例如:
    int a[30];
    int *p=a; /*指针的初始化*/
    在定义指针变量p的同时,将数组a的起始地址赋值给指针变量p,而不是赋值给指针p指向的变量。
    (2)用数组第0个元素地址做首地址。形式为:
    p=&a[0];
    数组名a与数组元素a[0]的地址相同,都是数组的起始地址,因此也可以将&a[0]赋值给指针p。
    3.利用指针引用一维数组元素
    如果指针变量p指向数组a的第一个元素(即第0号元素),即p=a,则
    (1)p+i和a+i就是数组元素a[i]的地址,即它们指向数组a的第i+1个元素,即i号元素。
    (2)*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i];
    (3)指向数组元素的指针变量也可以带下标,如p[i]与*(p+i)等价。所以,a[i]、*(a+i)、p[i]、*(p+i)四种表示方法全部等价。
    (4)指针变量可以通过本身值的改变来实现对不同地址的操作,既可以使用p++。因为数组名表示数组的起始地址,所以数组名也可以称为指针,但是数组名是一个特殊的指针,它是指针常量,其值在程序整个运行过程中都不能被改变,只代表数组的起始地址。所以,如果a是一个数组名,它是一个指针常量,像“a++”或者“a=a+2”这些语句都是错误的。

    综上所述,把指针与一维数组的联系归纳为下表(针对int a[10],*p=a)

    表达式含义
    &a[i],a+i,p+i引用数组元素a[i]的地址
    a[i]、*(a+i)、p[i]、*(p+i)引用数组元素a[i]
    p++、p=p+1表示p指向下一数组元素,即a[1]
    *p++、*(p++)先取p所指向的存储单元的内容*p,再使p指向下一个存储单元
    *++p、*(++p)先使指针p指向下一个存储单元,然后取改变后的指针p所指向的存储单元内容*p
    (*p)++取指针p所指的存储单元内容作为该表达式的结果值,然后使p所指对象的值加1,即*p=*p+1;指针p的内容不变

    例:
    从键盘输入10个数,利用指针法输入、输出数组。

    #include<stdio.h>
    void main()
    {
    	int	i,*p,a[10];
    	p=a;
    	for(i=0;i<10;i++)
    		scanf("%d",p++);
    	printf("\n");
    	p=a;
    	for(i=0;i<10;i++)
    		printf("a[%d]=%d\n",i,*p++);
    }
    

    4.指向二维数组的指针

    定义一个二维数组:
    int a[3][4];

    二维数组a的各种表示形式及其含义

    表示形式含义
    a数组a的起始地址,也是数组第0行的首地址
    a+i、&a[i]第i行的起始地址
    *(a+i)、a[i]第i行第0列元素的起始地址
    *(a+i)+j、a[i]+j,&a[i][j]第i行第j列元素的起始地址
    *( *(a+i)+j)、*(a[i]+j)、a[i] [j]第i行第j列元素的值

    注意:基于一维数组有a[0]和*(a+0)等价,a[1]和*(a+1)等价,a[2]和*(a+2)等价,因此第i行第j列地址也可以表示为*(a+i)+j,即&a[i][j]=a[i]+j=*(a+i)+j。
    利用指向二维数组元素的指针变量,可以完成二维数组数据的操作处理。
    (1)定义与二维数组相同类型的指针变量;
    (2)在指针变量与要处理的数组元素之间建立关联;
    (3)使用指针的运算就可以访问到任何一个数组元素,完成操作处理。

    例1:
    利用指针变量及指针变量的自增运算,输出二维数组所有元素的值。

    #include“stdio.h”
    void main()
    {
    		int 	a[3][3]={{0,1,2},{3,4,5},{6,7,8}};
    		int	*p,*q;
    		p=a[0];
    		q=&a[2][2];
    		while(p<=q)
    			{ 
    					printf("%d   ",*p);
    					p++;
    		    }
    		  printf("\n");
    }
    

    例2:

    利用数组指针求给定nxn矩阵的转置矩阵,并计算对角线元素之和。
    分析:

    数组指针是指向数组的指针变量,也叫行指针变量。

    如有数组指针变量p和二维数组a[3][4],p=a或p=&a[0]说明p指向了数组a的第0行,p+1指向了数组的第一行,p+i指向了数组的第i行,也说明了p+i等价于&a[i]。
    *(p+i)等价于a[i]或*(a+i),*((p+i)+j)等价于*(a[i]+j)、*((a+i)+j)、a[i][j]。

    要将一个矩阵转置,只要将这一个矩阵的上三角矩阵与其关于主对角线对称的下三角阵交换即可,也就是将a[i][j]和a[j][i]交换。

    源程序:

    #include<stdio.h>
    #define N 4
    void mian()
    {
    	int a[N][N],(*p)[N];
    	int i,jjt,s=0;
    	printf("input a:\");
    	for(i=0;i<N;i++)
    	{ 
    			printf("input the %dth row:\n",i+1);
    			for(j=0;j<N;j++)
    					scanf("%d",&a[i][j]);
    	}
    	p=a;
    	for(i=0;i<N;i++)
    	{
    		s+=*(*(p+i)+i);				/*累加对角线上的元素*/
    		for(j=i+1;j<N;j++)			/*交换a[i][j]和a[j][i]*/
    			{
    				t=*(*(p+i)+j);
    				*(*(p+i)+j)=*(*(p+j)+i);
    				*(*(p+j)+i)=t;
    			}
    	}
    	for(i=0;i<N;i++)						/*输出转置后的矩阵*/
    	{
    		for(j=0;j<N;j++)
    			printf("%4d",*(*(p+i)+j));
    		printf("\n");
    	}
    	printf("s=%d\n",s)
    }
    
    更多相关内容
  • 维数组在概念上是二的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6...行中的 4 个元素也是依次存放。数组 a
  • C语言指针数组数组每个元素都是指针)详解 C语言二数组指针(指向二数组的指针)详解 如果个数组中的所有元素保存的都是指针,那么我们就称它为指针数组指针数组的定义形式一般为: dataType *arrayName...

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

    如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。指针数组的定义形式一般为:

    dataType *arrayName[length];
    

    [ ]的优先级高于*,该定义形式应该理解为:

    dataType *(arrayName[length]);
    

    括号里面说明arrayName是一个数组,包含了length个元素,括号外面说明每个元素的类型为dataType *

    除了每个元素的数据类型不同,指针数组和普通数组在其他方面都是一样的,下面是一个简单的例子:

    #include <stdio.h>
    int main(){
        int a = 16, b = 932, c = 100;
        //定义一个指针数组
        int *arr[3] = {&a, &b, &c};//也可以不指定长度,直接写作 int *arr[]
        //定义一个指向指针数组的指针
        int **parr = arr;
        printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
        printf("%d, %d, %d\n", **(parr+0), **(parr+1), **(parr+2));
        return 0;
    }
    

    运行结果:

    16, 932, 100
    16, 932, 100
    

    arr 是一个指针数组,它包含了 3 个元素,每个元素都是一个指针,在定义 arr 的同时,我们使用变量 a、b、c 的地址对它进行了初始化,这和普通数组是多么地类似。

    parr 是指向数组 arr 的指针,确切地说是指向 arr 第 0 个元素的指针,它的定义形式应该理解为int *(*parr),括号中的*表示 parr 是一个指针,括号外面的int *表示 parr 指向的数据的类型。arr 第 0 个元素的类型为 int *,所以在定义 parr 时要加两个 *

    第一个 printf() 语句中,arr[i] 表示获取第 i 个元素的值,该元素是一个指针,还需要在前面增加一个 * 才能取得它指向的数据,也即 *arr[i] 的形式。

    第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,*(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),**(parr+i) 表示获取第 i 个元素指向的数据。

    指针数组还可以和字符串数组结合使用,请看下面的例子:

    #include <stdio.h>
    int main(){
        char *str[3] = {
            "Gakki",
            "is",
            "my girlfriend."
        };
        printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
        return 0;
    }
    

    运行结果:

    Gakki
    is
    my girlfriend.
    

    需要注意的是,字符数组 str 中存放的是字符串的首地址,不是字符串本身,字符串本身位于其他的内存区域,和字符数组是分开的。

    也只有当指针数组中每个元素的类型都是char *时,才能像上面那样给指针数组赋值,其他类型不行。

    为了便于理解,可以将上面的字符串数组改成下面的形式,它们都是等价的。

    #include <stdio.h>
    int main(){
        char *str0 = "c.biancheng.net";
        char *str1 = "C语言中文网";
        char *str2 = "C Language";
        char *str[3] = {str0, str1, str2};
        printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
        return 0;
    }
    

    测试

    #include <string.h>
    #include <conio.h>
    #include <stdio.h>
    
    void main()
    {
    	int a = 2014, b = 7, c = 29;
    	char *arr[3] = {&a,&b,&c};
    	int **parr = arr;
    	printf("\ta, b, c:\n\t%d,%d,%d\n", a, b, c);
    	printf("\t&a, &b, &c:\n\t%d,%d,%d\n", &a, &b, &c);
    	printf("\tarr[0], arr[1], arr[2]:\n\t%d,%d,%d\n", arr[0], arr[1], arr[2]);
    	printf("\t*(arr+0),*(arr + 1),*(arr + 2):\n\t%d,%d,%d\n", *(arr+0),*(arr + 1),*(arr + 2));
    	printf("\tparr+0,parr+1,parr+2:\n\t%d,%d,%d\n", parr+0,parr+1,parr+2);
    	printf(" \t*(parr + 0), *(parr + 1), *(parr + 2):\n\t%d,%d,%d\n", *(parr + 0), *(parr + 1), *(parr + 2));
    	printf("\t**(parr + 0), **(parr + 1), **(parr + 2):\n\t%d,%d,%d\n", **(parr + 0), **(parr + 1), **(parr + 2));
    }
    

    运行结果:
    在这里插入图片描述

    展开全文
  • 形式:一维指针数组的定义形式为:int【类型名】 *p【数组名】 [4]【数组长度】;由于[ ]比*优先级高,因此p先与[4]结合,形成p[4]的数组的形式。然后与p前面的“ * ”结合,“ * ”表示此数组是指针类型的,每个数组...
  • 1.1一维数组元素在内存分布 #include<stdio.h> #include<stdlib.h> #include<string.h> #define ARRAY_SIZE 8 void main() { int data[ARRAY_SIZE]={0,1,2,3,4,5,6,7}; int i; printf(...

    1 一维度数组与指针

    1.1一维数组元素在内存分布

    • #include<stdio.h>
      #include<stdlib.h>
      #include<string.h>
      
      #define ARRAY_SIZE 8
      
      void main()
      {
         int data[ARRAY_SIZE]={0,1,2,3,4,5,6,7};
         int i;
         printf("data address:0x%-8x\r\n",data);
         for(i=0; i<ARRAY_SIZE; i++)
         {
         	  printf("data[%-3d]:value %-3d,address:0x%-10x\r\n",i,data[i],&data[i]);
         }	
      }
      
      data address:0xbc4100d0
      data[0  ]:value 0  ,address:0xbc4100d0  
      data[1  ]:value 1  ,address:0xbc4100d4  
      data[2  ]:value 2  ,address:0xbc4100d8  
      data[3  ]:value 3  ,address:0xbc4100dc  
      data[4  ]:value 4  ,address:0xbc4100e0  
      data[5  ]:value 5  ,address:0xbc4100e4  
      data[6  ]:value 6  ,address:0xbc4100e8  
      data[7  ]:value 7  ,address:0xbc4100ec 

    结论为:
    1 数组元素的地址是线性的、连续的,这也是可以通过数组地址找到所有元素的原因。
    2  数组名代表数组指针,同时与首元素的地址相同

    1.2一维数组的指针

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    #define ARRAY_SIZE 8
    
    void main()
    {
       int data[ARRAY_SIZE]={0,1,2,3,4,5,6,7};
       int *pointer=data;
       int i;
       printf("data address:0x%-8x\r\n",data);
       for(i=0; i<ARRAY_SIZE; i++)
       {
       	  printf("data[%d]:value %-3d,address:0x%-10x\r\n",i,data[i],&data[i]);
       }	
    
    	for(i=0; i<ARRAY_SIZE; i++)
    	{
    	   printf("[%d]:value %-3d,address:0x%-10x\r\n",i,*(pointer+i),pointer+i);
    	}	 
    }
    
    data address:0x13bca160
    data[0]:value 0  ,address:0x13bca160  
    data[1]:value 1  ,address:0x13bca164  
    data[2]:value 2  ,address:0x13bca168  
    data[3]:value 3  ,address:0x13bca16c  
    data[4]:value 4  ,address:0x13bca170  
    data[5]:value 5  ,address:0x13bca174  
    data[6]:value 6  ,address:0x13bca178  
    data[7]:value 7  ,address:0x13bca17c  
    [0]:value 0  ,address:0x13bca160  
    [1]:value 1  ,address:0x13bca164  
    [2]:value 2  ,address:0x13bca168  
    [3]:value 3  ,address:0x13bca16c  
    [4]:value 4  ,address:0x13bca170  
    [5]:value 5  ,address:0x13bca174  
    [6]:value 6  ,address:0x13bca178  
    [7]:value 7  ,address:0x13bca17c 

    结论为:
             1 指向数组的指针加一表示加上每个元素的字节数
              2 指针可以引用一个数组

    2 二维度数组与指针

    2.1 二维数组元素在内存分布

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    #define ARRAY_X 7
    #define ARRAY_Y 5
    
    
    void main()
    {
       int data[ARRAY_X][ARRAY_Y]={0};
       int *pointer=data;
       int i,j,k,num=0;;
       for(i=0; i<ARRAY_X; i++)
       {
    	for(j=0;j<ARRAY_Y;j++)
    	{
    		data[i][j]=num;
    	}   
       } 	 
    
    	for(i=0; i<ARRAY_X;i++)
    	{
    	 printf("\r\n");
    	 for(j=0;j<ARRAY_Y;j++)
    	 {
    		 data[i][j]=num;
    		 
    		 printf("data[%d][%d]:%d,(address:0x%-10x)\r\n",i,j,data[i][j],&data[i][j]);
    	 }	 
    	}	     
    }
    
    
    data[0][0]:0,(address:0xfe8a3a10  )
    data[0][1]:0,(address:0xfe8a3a14  )
    data[0][2]:0,(address:0xfe8a3a18  )
    data[0][3]:0,(address:0xfe8a3a1c  )
    
    data[1][0]:0,(address:0xfe8a3a20  )
    data[1][1]:0,(address:0xfe8a3a24  )
    data[1][2]:0,(address:0xfe8a3a28  )
    data[1][3]:0,(address:0xfe8a3a2c  )
    
    data[2][0]:0,(address:0xfe8a3a30  )
    data[2][1]:0,(address:0xfe8a3a34  )
    data[2][2]:0,(address:0xfe8a3a38  )
    data[2][3]:0,(address:0xfe8a3a3c  )
    root@ubuntu:Array# 


     通过实际的地址信息,可以知道:二维数组在内存中是连续发布的,第0行的第一个元素->第0行的最后一个元素->第1行的第1个元素->第1行的最后一个元素,以次类推,地址增长

     

    2.2二维数组的指针

    2.2.1指针的使用方法

    声明一个二维数组 :int data[3][4]
     1 根据”数组名同时是数组首元素的地址“的原则,data是首元素的地址,二维数组data[3][4]的首元素是一维数组,所以data是一维数组data[0]的地址
     2 根据”数组名同时是数组首元素的地址“的原则,因此data的值等于&data[0],data[0]表示数组data[3][4]的首元素,这个首元素也是数组。根据“数组名同时是数组首元素的地址”的原则,data[0] 等于&data[0][0]
     3 根据“指针加1等于加上指针所指向的元素的大小“的原则,data+1并不等于data[0]+1,前者是4个单位,后者是1个单位“
     4 对一个指针取值得到的是该指针所指向对象的数值。data[0]表示一维数组data[0]的首元素即data[0][0]的地址,则*(data[0])表示元素data[0][0]的值

    2.2.2 指针、指针的指针、变量

    声明一个二维数组 :int data[3][4]

    本例中,哪些是一维数组指针,哪些是二维数组指针,哪些是元素值?
      二维数组指针:data
      一维数组指针:data[0]、data[1]、data[2]
      元素值:data[0][0]、data[0][1]、data[0][2]、data[0][3]

      c语言中,*号表示取值,&号表示取地址,按照原则,可以知道:
        data 是二维数组指针,*data是二维数组的元素即一维数组data[0];data[0]表示一维数组的地址,data[0]就表示一位数组data[0]首元素data[0][0]的地址。所以 **data的值就是data[0][0],data的值就是&&data[0][0]

     

    注意:比较简单的方法是,将指针转化为数组来理解,例如*(*(pointer+i)+j)的代码写成pointer[i][j],减少出错的概率,[]表示偏移后取值

     

    2.2.3 使用二维数组指针去访问元素

    声明一个二维数组 :int data[3][4],data代表这个二维数组的指针

    data第一个元素的地址,该元素是一维数组
    data+1第二个元素的地址,该元素是一维数组
    *(data+1)数组的地址,也是数组的首元素的地址,该数组是一维数组。*(data+1)的值于data+1相同,但是意义不一样。
    (*(data+1)+2)二维数组第1行第2列的元素的地址,也是一位数组data+1的第2个元素的地址。   
    *(*(data+1)+2)二维数组第一行第二列元素的值


       

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    #define ARRAY_X 3
    #define ARRAY_Y 4
    
    
    void main()
    {
       int data[ARRAY_X][ARRAY_Y]={0};
       int *pointer=data;
       int i,j,k,num=10;;
       for(i=0; i<ARRAY_X; i++)
       {
    	for(j=0;j<ARRAY_Y;j++)
    	{
    		data[i][j]=num++;
    	}   
       } 	 
    
       for(i=0; i<ARRAY_X;i++)
       {
    	printf("\r\n");
    	for(j=0;j<ARRAY_Y;j++)
    	{		
    		printf("data[%d][%d]:%d,(address:0x%-10x)\r\n",i,j,data[i][j],&data[i][j]);
    	}	
       }     
    
       printf("data:0x%x\r\n",data);
       printf("*data:0x%x\r\n",*data);   
       printf("**data:0x%x\r\n",**data);
    
    	printf("data[0][0]:0x%x\r\n",data[0][0]);
    	printf("&data[0][0]:0x%x\r\n",&data[0][0]);		
    	printf("data[0]:0x%x\r\n",data[0]);	
    	printf("&data[0]:0x%x\r\n",&data[0]);
    	printf("&data[0][0]:0x%x\r\n",&data[0][0]);
    
    	for(i=0; i<ARRAY_X;i++)
    	{
    	 printf("\r\n");
    	 for(j=0;j<ARRAY_Y;j++)
    	 {		 	
    		 printf("*(data+%d)):0x%x\r\n",i,*(data+i));	 
    		 printf("*(*(data+%d)+%d):%d\r\n",i,j,*(*(data+i)+j));
    	 }	 
    	}	
    	
    }
    
    
    data[0][0]:10,(address:0xf49fe5e0  )
    data[0][1]:11,(address:0xf49fe5e4  )
    data[0][2]:12,(address:0xf49fe5e8  )
    data[0][3]:13,(address:0xf49fe5ec  )
    
    data[1][0]:14,(address:0xf49fe5f0  )
    data[1][1]:15,(address:0xf49fe5f4  )
    data[1][2]:16,(address:0xf49fe5f8  )
    data[1][3]:17,(address:0xf49fe5fc  )
    
    data[2][0]:18,(address:0xf49fe600  )
    data[2][1]:19,(address:0xf49fe604  )
    data[2][2]:20,(address:0xf49fe608  )
    data[2][3]:21,(address:0xf49fe60c  )
    data:0xf49fe5e0
    *data:0xf49fe5e0
    **data:0xa
    data[0][0]:0xa
    &data[0][0]:0xf49fe5e0
    data[0]:0xf49fe5e0
    &data[0]:0xf49fe5e0
    &data[0][0]:0xf49fe5e0
    
    *(data+0)):0xf49fe5e0
    *(*(data+0)+0):10
    *(data+0)):0xf49fe5e0
    *(*(data+0)+1):11
    *(data+0)):0xf49fe5e0
    *(*(data+0)+2):12
    *(data+0)):0xf49fe5e0
    *(*(data+0)+3):13
    
    *(data+1)):0xf49fe5f0
    *(*(data+1)+0):14
    *(data+1)):0xf49fe5f0
    *(*(data+1)+1):15
    *(data+1)):0xf49fe5f0
    *(*(data+1)+2):16
    *(data+1)):0xf49fe5f0
    *(*(data+1)+3):17
    
    *(data+2)):0xf49fe600
    *(*(data+2)+0):18
    *(data+2)):0xf49fe600
    *(*(data+2)+1):19
    *(data+2)):0xf49fe600
    *(*(data+2)+2):20
    *(data+2)):0xf49fe600
    *(*(data+2)+3):21

    2.2.4 指向二维数组的指针

     在编写函数时,入参通常会是一个二维数组的指针,怎样正确访问这个二维数组的指针呢?

    声明一个二维数组 :int data[3][4]。

    声明一个指针int (* pointer)[4],该指针指向一个包含4个元素的数组.

    [4]通知编译器,每次pointer+1将会移动4个单位的长度。

    错误的声明:int  ** pointer,等价于int (* pointer)[1],编译器不知道宽度,每次pointer+1只会移动1个单位的长度

    错误的声明:int  * pointer[4],变成了指针数组,指针指向整型数。

    void main()
    {
       int data[ARRAY_X][ARRAY_Y]={0};
       int (*pointer)[ARRAY_Y]=data;
       int i,j,k,num=10;;
       for(i=0; i<ARRAY_X; i++)
       {
    	for(j=0;j<ARRAY_Y;j++)
    	{
    		data[i][j]=num++;
    	}   
       } 	 
    
       for(i=0; i<ARRAY_X;i++)
       {
    	printf("\r\n");
    	for(j=0;j<ARRAY_Y;j++)
    	{		
    		printf("data[%d][%d]:0x%x,(address:0x%-10x)\r\n",i,j,data[i][j],&data[i][j]);
    	}	
       }     
    
       printf("data:0x%x\r\n",data);
       printf("*data:0x%x\r\n",*data);   
       printf("**data:0x%x\r\n",**data);
    
    	printf("data[0][0]:0x%x\r\n",data[0][0]);
    	printf("&data[0][0]:0x%x\r\n",&data[0][0]);		
    	printf("data[0]:0x%x\r\n",data[0]);	
    	printf("&data[0]:0x%x\r\n",&data[0]);
    	printf("&data[0][0]:0x%x\r\n",&data[0][0]);
    
    	for(i=0; i<ARRAY_X;i++)
    	{
    	 printf("\r\n");
    	 for(j=0;j<ARRAY_Y;j++)
    	 {		 	
    		 printf("*(pointer+%d)+%d: 0x%x\r\n",i,j, *(pointer+i)+j);		 
    		 printf(" *(*(pointer+%d)+%d): 0x%x\r\n",i,j, *(*(pointer+i)+j));
    	 }	 
    	}	
    	
    }
    
    
    
    
    data[0][0]:0xa,(address:0xb8a93be0  )
    data[0][1]:0xb,(address:0xb8a93be4  )
    data[0][2]:0xc,(address:0xb8a93be8  )
    data[0][3]:0xd,(address:0xb8a93bec  )
    
    data[1][0]:0xe,(address:0xb8a93bf0  )
    data[1][1]:0xf,(address:0xb8a93bf4  )
    data[1][2]:0x10,(address:0xb8a93bf8  )
    data[1][3]:0x11,(address:0xb8a93bfc  )
    
    data[2][0]:0x12,(address:0xb8a93c00  )
    data[2][1]:0x13,(address:0xb8a93c04  )
    data[2][2]:0x14,(address:0xb8a93c08  )
    data[2][3]:0x15,(address:0xb8a93c0c  )
    data:0xb8a93be0
    *data:0xb8a93be0
    **data:0xa
    data[0][0]:0xa
    &data[0][0]:0xb8a93be0
    data[0]:0xb8a93be0
    &data[0]:0xb8a93be0
    &data[0][0]:0xb8a93be0
    
    *(pointer+0)+0: 0xb8a93be0
     *(*(pointer+0)+0): 0xa
    *(pointer+0)+1: 0xb8a93be4
     *(*(pointer+0)+1): 0xb
    *(pointer+0)+2: 0xb8a93be8
     *(*(pointer+0)+2): 0xc
    *(pointer+0)+3: 0xb8a93bec
     *(*(pointer+0)+3): 0xd
    
    *(pointer+1)+0: 0xb8a93bf0
     *(*(pointer+1)+0): 0xe
    *(pointer+1)+1: 0xb8a93bf4
     *(*(pointer+1)+1): 0xf
    *(pointer+1)+2: 0xb8a93bf8
     *(*(pointer+1)+2): 0x10
    *(pointer+1)+3: 0xb8a93bfc
     *(*(pointer+1)+3): 0x11
    
    *(pointer+2)+0: 0xb8a93c00
     *(*(pointer+2)+0): 0x12
    *(pointer+2)+1: 0xb8a93c04
     *(*(pointer+2)+1): 0x13
    *(pointer+2)+2: 0xb8a93c08
     *(*(pointer+2)+2): 0x14
    *(pointer+2)+3: 0xb8a93c0c
     *(*(pointer+2)+3): 0x15

    3 指针的指针的指针 

    3.1 指向二维数组的指针--元素为基本类型

     声明一个二维指针数组:int * p_data[3][4]

            这是一个二维数组,数组元素中存放的是指针,指针指向一个整型数。

       int *(*pointer)[4]

         这是一个指针,指向一个一维数组,该一维数组长度为4,数组的每个元素是一个指向整型数的指针。

     如何使用   pointer来访问p_data的值呢?

        pointer=p_data;

     p_data[i][j] 等价于pointer[i][j],等价于*(*(pointer+i)+j)  ; 

    *(p_data[i][j])等价于*(pointer[i][j],等价于 **(*(pointer+i)+j)

    3.2 指向二维数组的指针--元素为结构体

    声明结构体
    
    typedef struct avl{
    int name[4];
    int age;
    }AVL;
    
    定义宏
    #define ARRAY_X 3
    #define ARRAY_y 6
    
    
    声明二维结构提指针数组
    AVL* pointer[ARRAY_X][ARRAY_y];    
    
    声明指向数组的指针,数组的长度为6,每个元素为存放AVL类型指针
    AVL*(*ppp)[ARRAY_y];
    
    ppp=pointer;
    
    引用方法:
    ppp[x][y]   
    ppp[x][y])->name
    ppp[x][y])->age
    

    二维数组指针的关键是数组的宽度,告诉编译器每次移动一个单位需要偏移多少个字节。

    展开全文
  • 维数组数组指针详解

    千次阅读 多人点赞 2020-07-26 18:18:53
    新的理解:我们可以这样认为,a可以看作是一个一维数组,包含2个元素,每个元素恰好是包含3个整型的元素,a这个名字的值成了指向一个包含3个整型元素的数组指针(你学过数组指针就该知道,他们是一个道理,后面我...

    二维数组

    深入理解二维数组

    • 首先定义一个二维数组

      int a[2][3]={{1,2,3},{4,5,6}};
      #or int a[2][2]={1,2,3,4};
      

      新的理解:我们可以这样认为,a可以看作是一个一维数组,包含2个元素,每个元素恰好是包含3个整型的元素,a这个名字的值成了指向一个包含3个整型元素的数组的指针(你学过数组指针就该知道,他们是一个道理,后面我会讲解数组指针)

    • 然后开始讨论二维数组和数组名的关系

      a表示的是整个数组的首地址,a[0]表示的是第一行的首地址,这两者在数值上是一样的,但含义不同(或者说类型不同),数组名a是对于整个数组,a[0]是对于第一行。

    #打印 a a[0] 的值和 a[0][0] 的地址
    cout << a << endl;#0x7ffffffee120
    cout << a[0] << endl;#0x7ffffffee120	
    cout << &a[0][0] << endl;#0x7ffffffee120
    

    ​ 所以a、a[0]的值和 a[0][0]的地址三个表达指向一个地址。

    • 接着看每一行

      cout << a[0] << endl;#0x7ffffffee120
      cout << a[1] << endl;#0x7ffffffee12c
      

      输出的结果是每行的首地址,两个地址之间相差12个字节,也就是三个int的大小。

    • 下面我们通过a[0]&a[0][0]这两个地址推导出其他位置的元素。

      # 由a[0]推出其他,这里以第1行第1列为例
      cout << a[0+1]+1 << endl;			#0x7ffffffee130
      cout << *(a[0+1]+1) << endl;		#5
      cout << a[0]+4 << endl;				#0x7ffffffee130
      cout << *(a[0]+4) << endl;			#5
      
      # 由&a[0][0]推出其他, 这里以第1行第1列为例
      cout << &a[0][0]+4<< endl;		#0x7ffffffee130
      cout << *(&a[0][0]+4) << endl;	#5
      

      前两行通过加a[0]的索引得到其他行的首地址,然后再加偏移量得到元素地址,解引用获得该地址的值。

      之后两行是直接计算a[0]的偏移量得到元素地址,解引用获得该元素地址的值。最后两行与直接加偏移量的情况相同。

    • 由数组名得到其他元素

      a
      

      a是数组的名字,它的类型是“指向包含三个整型元素数组的指针”,默认指向第一行。

      a+1
      

      现在它指向了第二行,可以理解为当一个int*的指针指向一个数组的某一个int时,++他便指向了后一个int,同理,这里的数组指针指向了一个数组,所以++他就要指向下一个数组。

      *(a+1

      若是int*解引用后我们拿到了int类型数据,那数组指针呢?实际上我们对一个数组的指针解引用,拿到的是一个数组

      *(a+1== a[1]
      

      *(a+1)就是第二行的数组名,如果你觉得这样表达很奇怪,那么a[1]和他意义相同。

      我们现在拿到这个二维数组的第二行,第二行实际上就是一个一维数组,所以或许我们所有的处理都可以使用一维数组的方式。

      *(a+1+ 1
      

      让他指向了这个数组中的第2个元素。

      **(a+1+ 1

      最后一步就可以拿到想要的值。

      我们来看看一些关于取地址的问题

      printf("%d\n",sizeof(a+1));//8//第二行的地址(指针的大小)
      printf("%d\n",sizeof(&a[0]+1));//8
      printf("%d\n",sizeof(*(&a[0]+1)));//12
      

      1、a是一个数组指针,加一后指向下一行他还是指针,sizeof中就是指针的大小了。

      2、给a[0]取地址?a[0]是一个一维数组的名字,也就是一个指针,再次取地址后的结果就是一个二级指针。而之前我们对数组指针解引用得到数组名,这次刚好相反,所以&arr[0]你可以理解为,我们现在拿到了一个数组指针,对数组指针+1就是让他指向第二行,sizeof中就是指针的大小。(所以数组指针也叫二级指针)

      3、对数组指针解引用拿到了第二行数组的名字,sizeof他就是第二行大小。

    • 最后进行个小测试

      int a[2][3] = {0};
      printf("%d\n",sizeof(a));//24//输出这个二维数组的大小
      printf("%d\n",sizeof(a[0][0]));//4//第一个元素的大小(int)
      printf("%d\n",sizeof(a[0]));//12//第一行的数组的大小
      printf("%d\n",sizeof(a[0]+1));//8//第一行第二个元素的地址(指针的大小)
      printf("%d\n",sizeof(*(a[0]+1)));//4//第一行第二个元素的大小
      printf("%d\n",sizeof(a+1));//8//第二行的地址(指针的大小)
      printf("%d\n",sizeof(*(a+1)));//12//第二行的大小
      printf("%d\n",sizeof(&a[0]+1));//8//第二行的地址(指针的大小)
      printf("%d\n",sizeof(*(&a[0]+1)));//12//第二行的大小
      printf("%d\n",sizeof(*a));//12//第一行的大小
      printf("%d\n",sizeof(a[2]));//12//虽然越界了但是sizeof只是一个关键字他不关心这块空间是否真的存在
      

      数组指针

    为了更好的理解指针和二维数组的关系,我们先来定义一个指向 a 的指针变量 p:int (*p)[3] = a;

    括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [3],这正是 a 所包含的每个一维数组的类型。[ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4]),p 就成了一个指针数组,而不是二维数组指针。

    对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [3],那么p+1就前进 3×4 = 12 个字节,p-1就后退 12 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指向二维数组的下一行,p-1会使得指针指向数组的上一行。

    指针数组和二维数组指针有着本质上的区别:指针数组是一个数组,只是每个元素保存的都是指针。二维数组指针是一个指针,它指向一个二维数组,以上面的 a为例,它占用 8个字节的内存。

    等价关系:

    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)

    • 小练习

      int main()
      {
      	int arr[][3] = { 1, 2, 3, 4, 5, 6 };
      	int(*p)[3];
      	p = arr;
      	cout << p[0][0] << " " << *(p[0] + 1) << " " << (*p)[2] << endl;
      	return 0;
      }
      

      1、p[0][0]按照下标访问第一行第一个元素,输出1。
      2、*(p[0] + 1)这个让第一行指针指向第二个元素然后解引用,输出2。
      3、(*p)[2]等同于 *(*p+2),先解引用数组指针拿到第一行数组名,然后加到第3个位置解引用,输出3。

    二维数组的传参

    • 使用二维数组的传统定义方法传递参数

      如果把数组名作为函数的参数的话,在编译的时候这个数组参数会自动退化为指针,因此以下两种写法虽然不同,但在编译之后是一样的,数组会退化成数组指针。

    #include <iostream>
    using namespace std;
    /*以下两种写法本质上是一样的*/
    int func1(int (*arr)[4]) {
    	arr[0][2] = 20;
    	return 0;
    } 
    int func2(int arr[][4]) {
    	arr[0][2] = 30;
    	return 0;
    }
    int main(){
    	int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; 
    	func2(array);
    	cout << array[0][2] << endl;//fun1: 20 or fun2: 30
    	return 0;
    }
    
    • 使用动态分配内存的方式申请空间,可以使用**传递参数

      使用哪种方法定义的就使用哪种方式传参。

    #include <iostream>
    using namespace std;
    int func1(int **arr) {
    	cout << arr[0][1]<< endl;
    	arr[0][2] = 20;    
    	return 0;
    }
    int main(){
        int rows=3 ;
        int cols=4 ;
        int **arr = new int*[rows];//先使一个二级指针指向数组指针的地址
        for(int i = 0 ; i < rows ;++i )
        {
            arr[i] = new int [cols]();//为一级指针分配地址
        }
        arr[0][1]=100;
        func1(arr);
        cout << arr[0][2]<< endl;;
        //释放空间
        for(int i = 0; i < rows ;++i)
        {
            delete [] arr[i];//先释放二维数组中每个元素指向的数组
            arr[i] = NULL;
        }
        delete [] arr;//在释放该数组指针;
        arr = NULL;
    }
    
    展开全文
  • 概念详解:指针指针与“int a”,...一维数组:定义一维数组之后,即在内存中分配一段连续的地址空间,如C语言中,int num[5],在32位系统中,int占据4字节,现假设num[0]的地址空间为0x00000004,那么num[...
  • 维数组下面的代码先定义了一个整数二维数组,board[3][3] int board[3][3]={ {'1','2','3'}, {'4','5','6'}, {'7','8','9'} }; printf("*board:%9d\n",*
  • 数组指针和指针数组

    万次阅读 多人点赞 2019-09-17 16:39:06
    首先,理解一下数组指针和指针数组这两名词: “数组指针”和“指针数组”,只要在名词中间加上“的”字,就知道中心了...(*p)[n]:根据优先级,先看括号内,则p是一指针,这指针指向一个一维数组,数组长...
  • 1.一维数组指针表示 int a[10]; int *p; p=&a[0]; 注意 数组名a其实是个指针常量,一次不可赋值 p=a; 和p=&a[0];是等价的,指针默认指向数组元素的首地址 可写成 int a[10]; int *p=a; 数组元素可以...
  • 指针维数组元素引用

    千次阅读 2020-12-30 16:30:24
    二维数组元素指针引用 指针与一维数组和二维数组 1.定义 2.关系 3.数组指针和指针数组的区别 数组指针(也称行指针) ... //该语句是定义一个数组指针,指向含4个元素一维数组。 p=a; //将该二维数组的首地址赋给
  • 用于比较指针数组和数组指针实现算法的差异,利用函数返回指针实现。 可作为研究C语言指针使用的范例程序。 有源代码和实现结果图。
  • 用指向一维数组a的指针变量实现对二维数组b中各元素的输入和输出 编写程序,用指向一维数组指针变量p实现对二维数组b中各元素的输入和输出。要求:输出用指针变量的多种表现形式进行数组元素的多次输出。 完蛋 ...
  • 1、说起指针之前,先来看看下面这例子。 #include <stdio.h> #include <stdlib.h> int malloc_pointer(char *p) { if(p == NULL) { p = (char *)malloc(10); } return 0; } int free_pointer...
  • 在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有 ...但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存: C 语言中的二维数组是按行排列的,也就是先存放 a .
  • C语言二维数组指针(指向二维数组指针)详解

    万次阅读 多人点赞 2020-05-27 17:43:22
    声明!本文转载仅为方便学习使用! 如有需要,请访问C语言二维数组指针(指向二维数组指针)详解 二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续...但在内存中,a 的分布是一维线性的,整
  • 数组与指针、指针数组、数组指针的用法

    万次阅读 多人点赞 2018-03-12 18:16:20
    二维数组指针⑴ 用指针表示二维数组元素。要用指针处理二维数组,首先要...而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组元素都是一个一维数组下面我们讨论指针和二维数组元素的...
  • C++ 对象指针数组

    千次阅读 2019-04-21 12:27:40
    typedef Student * PStudent; PStudent *stud;//Student **stud; stud=new PStudent[5];//stud=new Student *[5];一维都是一指针 for(int k=0;...//为每一维指针new一类 代替: typedef Stu...
  • 可以存储一组或者多组数值的变量,里面包含多个元素数组每个成员都是一个数组元素。 一维数组 定义:类型 数组名[常量表达式] = {值1, 值2, 值3…}; int a[3] = {0, 1, 2}; float f[2] = {1.2, 2.3, 3.14}; ...
  • int *p[3]与int (*p)[3]的区别*p[3]这个是一个指针数组,它所代表的意思是数组中的个元素都是一个指针变量,而(*p)[3],p是一个指针变量,表示指向一个含有3个整型元素的一维数组。 代码如下:int i,j; int a[2]...
  • int b[10]在c中,在几乎所有使用数组名的表达式中,数组名的值是指针常量,也就是数组第1个元素的地址(要注意数组名在这里指的是个地址)。它的类型取决于数组元素的类型:如果它们是int类型, 那么数组名的...
  • 对于二维数组数组指针的详解
  • 指针数组、数组指针——用指针访问数组方法总结

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

    千次阅读 2022-04-12 21:07:45
    C语言文章更新目录 C语言学习资源汇总,史上最全面总结,没有之一 C/C++学习资源(百度云盘链接) ...C语言数组——一维数组 C语言数组——二维数组 C语言数组——字符数组 C语言中常用的6字符串处理函
  • 一维数组指针: 1、一维数组名: 对于这样的一维数组:int a[4]; a作为数组名就是我们数组的首地址, a是一地址常量 .  首先说说常量和变量的关系, 对于变量来说, 用箱子去比喻再好不过了, 声明一变量就声明一...
  • 使用指针输出二维数组的任意元素

    千次阅读 2017-08-31 08:10:15
    使用指针输出二维数组元素
  • 一维数组&指针

    2019-08-24 10:08:50
    导言:对于一维数组而言,数组作形参↔指针变量作形参,都可以用下标法和指针法来引用数组元素。 1、数组作形参​
  • 程序将倒数第二行改为:p(*a,9...如果要让一维指针指向二维数组,则我们必需告诉指针所指向的数组的最后一维包含多少个元素,即告诉指针我们将传递一个二维数组的首地址给指针。如上面的例子,应该这样来定义指针:i...
  • C语言之指向一维数组指针

    万次阅读 多人点赞 2018-04-17 11:41:53
    int array[5] = {1, 2, 3, 4, 5}; // 定义数组 ...上述三条语句分别定义了数组, 指向数组元素指针和指向数组指针. 内存情况如图示: 对于指向数组元素指针很好理解, 但是怎样理解 指向数组指针...
  • C语言指针重点难点整理(详解)(包括一维数组,二维数组的元素指针,二维数组的行指针做函数参数,指针数组,行指针数组) 笔者学指针之前: 呵呵,听闻指针是C语言的难点,我倒要见识一下,到底有多难 笔者学完...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,106
精华内容 39,242
关键字:

一维对象指针数组的每个元素