当前位置:首页 » 文件传输 » 一级指针访问二维数组元素
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

一级指针访问二维数组元素

发布时间: 2022-10-16 02:27:30

① C语言中指针引用二维数组元素的问题

下面是本人文库中的文章,关于二维数组与指针的讲解。

1、两条基本准则:
a、首先要明白,指针运算符的作用,我用一言以概之,你在哪里使用都不会错。指针运算符*的作用是求出*后面所指地址里的值。因此只要*后面的变量表示的是一个地址就可以使用*运算符,来求出这个地址中的值,你不用管这个地址的表示形式是怎样的,只要是地址就可以使用*来求出地址中的值。

b、[ ]这个运算符的的运算法则是,把左侧的地址加上[ ]内的偏移量然后再求指针运算,注意有[ ]运算符的地方就有个隐含的指针,比如x[2]表示的就是将指针x偏移2个单位量后再求指针运算。也就说x[2]与*(x+2)是相等的。

2、对二维数组的讲解:
a、对一维数组地址的详细讲解:
比如一维数组a[5],众所周知,一维数组的数组名a表示的是第一个元素a[0]的地址,也就是说数组名与&a[0]是等价的,因此数组名a的地址,并不是这个一维数组的数组的地址。那么&a,表示的又是什么呢?因为,a是一个一维数组,所以&a表示的就是这个一维数组的地址,也就是说&a中的地址是一个包含有4个元素的一维数组的地址。就好比int i中的&i,才表示的是这个变量i的地址一样。

b、对二维数组地址的讲解:
比如二维数组b[3][4],我们首先从一维开始分析,众所周知b[0],b[1]分别表示的是二维数组中第一行第一个元素和第二行第二个元素的地址,也就是说b[0]是与&b[0][0]等价的,b[1]是与&b[1][0]等介的。因此数组名就与&b[0]等介的,也就是说数组名表示的是二维数组中第一行所包含的一维数组的地址,说简单一点,就是说二维数组名是二维数组中第一行的行地址。因此二维数组名b所包含的地址中包含有二维数组中第二维中元素的个数的一维数组,也就是b的地址中包含一个含有4个元素的一维数组的地址(也就是所谓的数组的数组了)。

c、对二维数组中地址的相加运算的讲解:
同样以b[3][4]为例来讲解,在上面讲到b[0]表示的是&b[0][0],因此对b[0]进行相加运算,比如b[0]+1,那么就将使地址偏移一个单位,也就是地址被偏移到了&b[0][1]处,也就是b[0]+1表示的是b[0][1]的地址。上面也讲到数组名b,表示的是一个一维数组的地址,因此对数组名进行偏移,比如b+1,则将使指针偏移一个一维数组的长度,也就是b+1,将是&b[1]的地址,因此b+1的地址,表示的是二维数组中第二行所包含的一维数组的地址,简单点就是第二行的行地址。
d、对二维数组的指针运算:
*b
在上面讲解过,因为b表示的是二维数组中第一行所包含的一维数组的地址,因此*b=*(b+0)=*(&b[0])=b[0],所以*b表示的是二维数组中第一行第一个元素的地址,即*b=&b[0][0],用语言来描术*(b+0)就是,把数组名的地址偏移0个单位,然后再求这个地址所包含的值。在二维数组中,这个值就是指的b[0],因此这个值是与b[0][0]的地址相等的,结果就是*(b+0)与b是相等的,这在多维数组中是个怪现象,至少本人无法理解这是为什么。因为对同一个地址,进行指针运算得到了不同的结果,比如*b和*b[0],因为b和b[0]都是相同的地址,但对他们进行指针运算却得到了不同的结果,*b得到了&b[0][0]的地址,而*b[0]得到了b[0][0]的值,这是对同一个地址进行指针运算却得到了不同的值,对于这个问题,无法理解。
*(b+1)和*(b+0)
对于*(b+1)也和*(b+0)是同样的道理,*(b+1)=b[1]。我们再来看*b[1],因为*b[1]=*(b[1]+0)=*(&b[1][0])=b[1][0],可以看出,这就是二维数组中第二行第一个元素的地址。
*(*(b+1)+1)
因为*(*(b+1)+1)=*(*(&b[1])+1)=*(b[1]+1)=*(&b[1][0]+1)=*(&b[1][1])=b[1][1],语言描术就是,b+1使地址偏移到了二维数组中第二行所包含的一维数组的地址(或第二行的行地址),然后再对这个行地址求指针(或求值)运算,因此就得到第二行第一个元素的地址,然后再对这个地址偏移一个单位,就得到第二行第二个元素的地址,再对这个地址进行指针运算,就得到了这个元素的值,即b[1][1],其他的内容可以以止类推。
e、对二维数组的指针和[ ]的混合运算
在下面的指针和[ ]的混合计算中,要记住两点关键法则,记住了这两点在哪里计算都不会出错
a、对于像b[1]这样的地址,最好应表示为&b[1][0]再进行偏移计算,比如对于b[1]+1,这不是直接在对b[1]加1,也就是b[1]+1不等于b[2],因为b[1]表示的是第二行行1个元素的地址,对其加1,应该表示的是第二行第二个元素的地址,也就是&b[1][1],而b[2]则表示的是第二行第一个元素的地址,因此错误,所以在计算时应把b[1]转换为&b[1][0]之后,才能直接进行地址的偏移,也就是说b[1]+1=&b[1][0]+1=&b[1][1],这样才能得到正确的结果,并且不会出错。
b、对于有小括号的地方,一定不要省略小括号。比如(&b[1])[1]与&b[1][1]将表示的是不同的结果,第二个是显然的,对于第一个(&b[1])[1]=*((&b[1])+1)=*(&b[1]+1)=*(&b[2])=b[2],可以看到,表示的是第3行第1个元素的地址,因此这两个的结果是显然不一样的。因此对于(b+1)[1]这样的运算,不能省略小括号,即(b+1)[1]=(&b[1])[1]=*((&b[1])+1)=*(&b[1]+1)=*(&b[2])=b[2],如果省略了小括号,则是(b+1)[1]=&b[1][1],这将是不易发现的错误。因此这是两个完完全全不同的符案。
c、总结,指针和[ ]混合运算2点关键,
第1:应把是地址的[ ]运算,转换为地址的形式,比如b[1]应转换为&b[1][0]。因为只有这样才能进行直接的地址相加运算,即&b[1][0]+1=&b[1][1],而b[1]+1不等于b[2]。

第2:有小括号的地方不能省略小括号,如(b+1)[1]=(&b[1])[1]=*((&b[1])+1)=*(&b[1]+1)=*(&b[2])=b[2],也&b[1][1]是完全不同的。

(*(b+1))[1] ,(*b)[1]
最简单的理解方法为*(b+1)和语句b[1]等价,即(*(b+1))[1]和语句b[1][1]是相同的,也就是二组数组第2行第2个元素的值b[1][1],理解方法2逐条解释,如上面的解释*(b+1)表示的是二维数组b的第二行第一个元素的地址,也就是b[1],然后再与后面的[1]进行运算,就得到b[1][1]。或者(*(b+1))[1]=*((*(b+1))+1)=*(*(b+1)+1)这个语句上面解释过。同理(*b)[1]=b[0][1]

*(b+1)[1]:
计算方法1把[ ]分解为指针来计算:因为[ ]运算符高于指针,因此应先计算[ ]再计算指针,因为[1]表示的是把左侧的地址偏移1个单位,再求指针,因此(b+1)[1]=*((b+1)+1),最后再计算一次指针运算,也就是*(b+1)[1]=**((b+1)+1)=**(b+2)=*(*(b+2))=*b[2]=b[2][0],可以看到,最后表示的是b中第3行第一个元素的值。
计算方法2把指针化为[ ]来计算:*(b+1)[1]=*(&b[1])[1]=*(*(&b[1]+1))=**(&b[2])=*b[2]=b[2][0],注意*((&b[1])[1])表达式中应把(&b[1])括起来,若不括起来,则[ ]运算符的优先级高于&运算符,因此(&b[1])[1]与&b[1][1]是不一样的,后一个表示的是第二行第二个元素的地址,而头一个(&b[1])[1]则表示的是,对b的第二行的行地址偏移1个单位后再求指针的结果,也就是*(&b[1]+1)=*(&b[2])=b[2],所以性质是不一样的。
(*b+1)[2]
计算方法1化简[ ]运算符:(*b+1)[2]=*((*b+1)+2)=*(*b+3)=*(&b[0][0]+3)=*(&b[0][3])=b[0][3],这里要注意*b表示的是b[0]=&b[0][0],在计算时最好不要代入b[0]来计算,而应把b[0]转换为&b[0][0]后再计算,因为b[0]+3,很容易被错误的计算为b[3],而实际上b[0]指向的是第一行第一个元素的地址,对其偏移3个单位应该是指向第一行第4个元素的地址,即&b[0][3],而b[3],则指向了第3行第1个元素的地址,这是不同的。
计算方法2化简*运算符:(*b+1)[2]=(b[0]+1)[2]=(&b[0][0]+1)[2]=(&b[0][1])[2]=*(&b[0][1]+2)=*(&b[0][3])=b[0][3],注意,在计算过程中小括号最好不要省略,省略了容易出错,因为[ ]运算符的优先给更高,如果省略了,某些地方将无法计算。比如(&b[0][0]+1)[2]=(&b[0][1])[2],如果省略掉括号,则成为&b[0][1][2],这对于二维数组来讲,是无法计算的。
(*(b+1))[5]
计算方法:(*(b+1))[5]=(*(&b[1]))[5]=(b[1])[5]=*(b[1]+5)=*(&b[1][0]+5)=*(&b[1][5])=b[1][5],结果等于第二行第6个元素的值。
f、注意,在二维或者多维数组中有个怪现象,比如对于多维数组a[n][m][i][j],那么这些地址是相同的,即数组名a, a[0], a[0][0], a[0][0][0], &a[0][0][0][0],都是相同的地址。而且对数组名依次求指针运算将得到,比如*a=a[0],*a[0]=a[0][0], *a[0][0]=a[0][0][0], *a[0][0][0]=a[0][0][0][0],可以看到,只有对最后这个地址求指针运算才真正得到了数组中的值,因此对数组名求指针运算,要得到第一个元素的值,应该****a,也就是对4维数组需要求4次指针运算。同样可以看到,对数组名进行的前三次指针运算的值都是相同的,即*a, **a, ***a和a的值都是&a[0][0][0][0]的值,这就是这个怪问题,按理说对地址求指针应该得到一个值,但对多维数组求指针,却得到的是同一个地址,只是这些地址所包含的内容不一样。

3、数组指针与二维数组讲解:

下面我们将以y[4]={1,2,3,4}这个一维数组为例来层层讲解,指针和数组的关系。
1、数组指针:
定义形式为:int (*p)[4];表示定义了一个指向多维数组的指针,即指针p指向的是一个数组,这个数组有4个元素,对这个指针p的赋值必须是有4个int元素的数组的地址,即只要包含有四个元素的数组的地址都能赋给指针p,不管这个数组的行数是多少,但列数必须为4。即int y[4],x[22][4];都可以赋给指针p。赋值方式为p=&y或p=x,对于&y和二维数组数组名前面已讲过,&y中的地址是一个包含有4个元素的一维数组的地址,二维数组名x也是一个含有4个元素的一维数组的地址,因此可以这样赋值。而这样赋值将是错误的p=y,或者p=x[0]; 因为y和x[0]的地址只包含一个元素,他们不包含一个数组,因此出错。
2.注意()必须有,如果没有的话则,int *p[4];则是定义了一个指针数组,表示每个数组元素都是一个指针,即p[2]=&i;指向一个int型的地址,而*p[2]则表示p[2]所指向的元素的值。
3.初始化数组指针p:
a、当把int y[4]赋给指针p时p=y将是错误的,正确的方式为p=&y因为这时编译器会检查赋给指针p的元素是否是含有四个元素的数组,如果是就能正确的赋值,但语句p=y中的y代表的是数组y[4]第一行第一列的元素的地址也就是&y[0]的地址,因此y指向的地址只有一个元素,而指针p要求的是有4个元素的数组的地址,因此语句p=y将出错。而&y也表示的是一个地址,因为数组名y表示的是&y[0]的地址,因此&y=&(&y[0])。可以把&y理解为是数组y[4]的第一行的行地址,即&y包含了数组y[4]的第一行的所有元素,在这里&y包含有4个元素,因则p=&y才是正确的赋值方法,在这里要注意,数组的某行的行地址是第本行的第一个元素的地址是相同的。
b、把x[22][4]赋给指针p有几种方法,方法一:p=x;我们这样来理解该条语句,首先x[0]表示的是二维数组x[22][4]的第1行第一列元素的地址,这个地址包含一个元素,这是显而易见的,而数组名x也表示一个地址,但这个地址包含的是一个数组(即数组的数组),这个数组是包含4个元素的数组,这4个元素就是数组x第一行的4个元素,也就是说x表示的是数组x[22][4]的第1行的行地址,即数组名x就包含了数组x[22][4]第1行的4个元素,因此这种赋值方式是正确的。这时指针p就相当于是数组名一样,比如p[2][1]访问的就是数组x的第3行的第2个元素。
c、方法二:p=x+1或者p=&x[1];注意必须要有地址运算符&,同理语句&x[1]表示的是数组x[22][4]第2行的行地址,因为x[1]表示的是数组x[22][4]第的第2行第1列的元素的地址,因此&x[1]表示的就是数组x的第2行的行地址,因为&x[1]这个地址包含了一个数组,这个数组的起始地址是从x[1]这个地址开始的,这,即数组x[22][4]中x[1]这一行的4个元素。在这一行中包含了4个元素。而x+1本身就是指的x[1]的地址。这时指针p的起始地址是&x[1],所以p[0][1]不再是访问的x的第一行第二个元素,而是访问的x的第二行第二个元素。
d、注意,再次提示,数组的某行的行地址是与本行的第一个元素的地址是相同的。

② 指针指向二维数组的几种方法

二维数组乃至多位数组本质就是顺序表,所以用只要指向首元素的指针就可以了。
另外就是使用数组指针,要注意语法声明。

③ 我想问下关于VC一级指针指向二维数组问题

先解释一下那个数据类型问题:
定义指针时可以这么写int*
p此时的int*则可以理解为整形指针类型,
在C#中一维数组的定义都是int[]
p,二维的是int[,]
p以此类推,可以看出
int[]也可以和int*类似的看待,所以也可以叫做整形数组类型。所以说p和A的数据类型不同,因为p为指针类型,A为数据类型。
A是二维数组的首地址,对应于双重指针,所以你那个p=A赋值应该是错的,应该把*p改成**p,一维数组对就单指针。

④ C语言指针指向一维数组与二维数组

⑤ 一维数组和二维数组的一级指针

直接举个例子:
int
p1[10];
int
p2[10][10];
p1
是就相当于&p1[0],*p1就相当于p1[0];
二维数组在c/c++就相当于一维数组的数组
所以
p2
相当于&p2[0],
*p2相当于&p2[0][0],
这时p2与*p2相等,**p2就相当于p2[0][0].

⑥ C++中编程问题,指针访问二维数组数组

如果是*(*p+j)你就应该循环3*4了;
你那程序应该像三楼那样写.

⑦ 怎样使用指针引用二维数组的元素

对于a[i][j](二维数组的大小为n×m)而言,
首先要搞清楚行指针和列指针
行指针:&a[i]或者a+i指向行,&a[i]=&*(a+i)=a+i
列指针:a[i]或*(a+i)指向列,a[i]等价于*(a+i)
元素的引用方式有如下三种方式
1.通过地址引用二维元素
*(&a[i][j]),
*(a[i]+j),
*(*(a+i)+j),
*(a[0]+m*i+j)
*(&a[0][0]+m*i+j)
(*(a+i))[j]
2.建立一个指针数组引用二维元素
int *p[3],a[3][2],i,j;
for(i=0;i<3;i++)
p[i]=a[i];//p[i]用来存放地址,a[i]为列地址
等价如下
(1) *(p[i]+j) 与*(a[i]+j)对应
(2)*(*(p+i)+j) 与*(*(a+i)+j)对应
(3)(*(p+i))[j] *(p[i]+j) 与*(a[i]+j)对应
(4)p[i][j] 与a[i][j]对应
3.建立一个行指针引用二维数组元素
int a[3][2],(*p)[2];
p=a;
(1) *(p[i]+j) 与*(a[i]+j)对应
(2)*(*(p+i)+j) 与*(*(a+i)+j)对应
(3)(*(p+i))[j] 与(*(a+i))[j]对应
(4)p[i][j] 与a[i][j]对应
例题如下
1.
#include<stdio.h>
main()
{
int score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
int i,j;
printf("输入学生号:0-2");
scanf("%d",&i);
printf("the score of No.%d are:\n",i);
for(j=0;j<4;j++)
printf("%d\t",*(*(score+i)+j));//score+i为列指针,*(score+i)为行指针
printf("\n");
}
2.
#include<stdio.h>
main()
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;
for(p=a[0];p<a[0]+12;p++)//使p依次指向下一个元素,a[i]和*(a+i)是指向列的指针;&a[i]或a+i是指向行的指针
{
if((p-a[0])%4==0)printf("\n");
printf("%4d",*p);//输出p指向的数组元素的值
}
printf("\n");
}
3
#include<stdio.h>
main()
{
int score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
int i,j;
printf("输入学生号:0-2");
scanf("%d",&i);
printf("the score of No.%d are:\n",i);
for(j=0;j<4;j++)
printf("%d\t",*(score[i]+j));
printf("\n");
}
4
#include<stdio.h>
main()
{
int score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
int i,j,*p;
printf("输入学生号:");
scanf("%d",&i);
printf("the score of No.%d are:\n",i);
for(p=score[i];p<score[i]+4;p++)
printf("%d\t",*p);//p+i指向第i行,*(p+i)指向第i行0列元素*(p+i)+j指向第i行j列元素,是列地址
printf("\n");
}
5.
#include<stdio.h>
main()
{
int score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
int i,j,*p;
printf("输入学生号:");
scanf("%d",&i);
printf("the score of No.%d are:\n",i);
for(p=score[i],j=0;j<4;j++)
printf("%d\t",*(p+j));
printf("\n");
}
6
#include<stdio.h>
main()
{
int score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
int i,j,(*p)[4];//指针变量p指向包括4个整型元素的一维数组;
p=score;//p指向二维数组0行元素,p+1所指向的元素是p所指向元素的下一行元素;
printf("输入学生号:0-2");
scanf("%d",&i);
printf("the score of No.%d are:\n",i);
for(j=0;j<4;j++)
printf("%d\t",*(*(p+i)+j));//p+i指向第i行,p是行指针,*(p+i)指向第i行0列元素,是列指针。*(p+i)+j指向第i行j列元素,是一个元素的地址
printf("\n");
}

⑧ 我想问下关于VC一级指针指向二维数组问题

先解释一下那个数据类型问题:
定义指针时可以这么写int* p此时的int*则可以理解为整形指针类型,
在C#中一维数组的定义都是int[] p,二维的是int[,] p以此类推,可以看出
int[]也可以和int*类似的看待,所以也可以叫做整形数组类型。所以说p和A的数据类型不同,因为p为指针类型,A为数据类型。
A是二维数组的首地址,对应于双重指针,所以你那个p=A赋值应该是错的,应该把*p改成**p,一维数组对就单指针。

⑨ C语言 怎么用指针输出一个二维数组的全部值

C语言的数组(不管多少维)在内存中都是线性储存的。所以用一级指针加偏移就可以访问所有元素。

举个例子,有一个10*10的二维数组a,这样就可以输出:

inta[10][10];

int*p=(int*)a;
inti;

for(i=0;i<10*10;i++)
printf("%d",*(p+i));