| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 550 人关注过本帖
标题:有关指针指向二维数组的小插曲,求个小问?(需要详解)
只看楼主 加入收藏
林浩
Rank: 2
等 级:论坛游民
帖 子:47
专家分:23
注 册:2011-1-12
结帖率:90.91%
收藏
已结贴  问题点数:20 回复次数:5 
有关指针指向二维数组的小插曲,求个小问?(需要详解)
觉得指针很有意思,所以想搞清楚。
  一个数组转置的问题:
#include<stdio.h>

void main()
{
    void zhuanzhi(int (*p1)[3], int (*p2)[3], int n);

    int a[3][3], b[3][3], i, j, *pa, *pb;

    printf("please input the a:\n");
    for (i = 0; i < 3; i ++)
    {
        for (j =0; j < 3; j++)
        {
            scanf("%d", &a[i][j]);
        }
    }

    pa= a[0];                     这里如果用 p=a;p=b就不行, 他们不是都是二维数组a的首行地址吗,有什么区别呢??
    pb= b[0];

    zhuanzhi(pa, pb, 3);

    printf("please output the b:\n");

    for (pb = b[0]; pb < b[0] + 9; pb++)
    {
        if ((b[0] - pb) % 3 == 0)
        {
            printf("\n");
        }
        printf("%4d", *pb);
    }
}

void zhuanzhi(int (*p1)[3], int (*p2)[3], int n)    如果这里和主函数中的(*p1)[3],(*p2)[3]都改成*p1,*p2程序就报错,为什么一定要定它的列数呢?
{
    int i,j;

    for (i = 0; i < n; i ++)
    {
        for (j = 0; j<n; j++)
        {
            *(*(p2+i)+j)  = *(*(p1+j)+i);
        }
    }
}

   在此小弟感谢你们的帮助!!!!!!!!
搜索更多相关主题的帖子: include please 
2011-02-27 12:29
cacker
该用户已被删除
收藏
得分:5 
提示: 作者被禁止或删除 内容自动屏蔽
2011-02-27 12:35
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:5 
int a[3][3], b[3][3], i, j, *pa, *pb;

这里如果用 p=a;p=b就不行, 他们不是都是二维数组a的首行地址吗,有什么区别呢??

不行  原因二楼已经说了  我也就不重复了
 对于一个指针 首先他是一个复合类型  它有自身的类型  还有它所指向的类型
对于一个确定的操作系统 比如XP   他自身的类型是确定的  是DWORD 这个很简单
比较难的是它所指向的类型  比如int * 这个你知道是指向整形的  但是如果是 int (*p)(int)这种类型呢?
首先他是一个指针,它指向
一个函数,这个函数的类型是
参数为一个整形,返回值为整型
指向数组的同理。。。。。。。。。。。。。。。

其实吧上面的弄清楚了就可以了  当然也可以搞个再发杂点的 把函数和数组结合起来  比如说   typedef int (*(*p)(int))[5];
首先p是个指针,它指向  一个函数,这个函数的参数为int类型  返回值为   指向一个长度为5的数组的指针  这个数组的类型为整形
这个过于复杂  可以不用掌握  
总之遇见一个指针要弄清楚三个问题  1.指针自身的类型(通常为DWORD)2.指针所指向的类型(重要)3.指针所指向类型的值

                                         
===========深入<----------------->浅出============
2011-02-27 14:15
liangjinchao
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:376
专家分:697
注 册:2010-11-8
收藏
得分:5 
二维数组和指针

二维数组和指针1、二维数组和数组元素的地址若有以下定义:int *p, a[3][4];


 



1)二维数组a由若干个一维数组组成在C语言中定义的二维数组实际上是一个一维数组,这个一维数组的每一个成员又是一个一维数组。如以上定义的a数组,则可视a数组由a[0]、a[1]、a[2]等三个元素组成,而a[0]、a[1]、a[2]等每个元素又分别是由4个整型元素组成的一维数组。可用a[0][0]、a[0][1]等来引用a[0]中的每个元素,其它依次类推。在第二节中已解释过,C语言中,在函数体中或在函数外部定义的一维数组名是一个地址常量,其值为数组第一个元素的地址,此地址的基类型就是数组元素的类型。在以上二维数组中,a[0]、a[1]、a[2]都是一维数组名,同样也代表一个不可变的地址变量,其值依次为二维数组每行第一个元素的地址,其基类型就是数组元素的类型。因此,对于二维数组,象a[0]++这样的表达式是非法的。若有表达式a[0]+1,表达式中1的单位应当是2个字节。在以上定义中,指针变量p的基类型与a[i](0≤i<3)相同,因此,赋值语句p=a[i];是合法的。我们已知a[i]也可以写成:*(a+i),故以上赋值语句也可写成:p=*(a+i);。

 

2)二维数组名也是一个地址常量二维数组名同样也是一个存放地址常量的指针,其值为二维数组中第一个元素的地址。以上a数组,数组名a的值与a[0]的值相同,只是其基类型为具有4个整型元素的数组类型。即a+0的值与a[0]的值相同,a+1的值与a[1]的值相同,a+2的值与a[2]的值相同,它们分别表示a数组中第零、第一、第二行的首地址。二维数组名应理解为一个行指针。在表达式a+1中,数值1的单位应是4×2个字节,而不是2个字节。赋值语句p=a;是不合法的,因为p和a的基类型不同。同样,对于二维数组名a,也不可以进行a++,a=a+i等运算。

 

3)二维数组元素的地址二维数组元素的地址可以由表达式&a[i][j]求得;也可以通过每行的首地址来表示。以上二维数组a中,每个元素的地址可以通过每行的首地址:a[0]、a[1]、a[2]等来表示。如:地址&a[0][0]可以用a[0]+0来表示,地址&a[0][1]可以用a[0]+1表示;若0≤i<3、0≤j<4,则a[i][j]的地址可用以下五种表达式求得:(1)&a[i][j](2)a[i]+j(3)*(a+i)+j(4)&a[0][0]+4*i+j (5)a[0]+ 4*i+j

 

在以上表达式中a[i]、&a[0][0]、a[0]的基类型都是int类型,系统将自动据此来确定表达式中常量1的单位是2个字节。但是不可以把求a[i][j]地址的表达式写成:a+4*i+j,因为a的基类型是4个整型元素的数组类型,系统将自动据此来确定常量1的单位是8个字节。

 

2、通过地址来引用二维数组元素若有以下定义:int a[3][4],i,j;且当0≤i<3、0≤j<4,则a数组元素可用以下五种表达式来引用:(1)a[i][j](2)*(a[i]+j)(3)*(*(a+i)+j)(4)(*(a+i))[j](5)*(&a[0][0]+4*i+j)

 

在(2)中,表达式*(a[i]+j)中,因为a[i]的基类型为int,j的位移量为2×j字节。

 

在(3)中,表达式*(*(a+i)+j)中,a的基类型为4个元素的数组,i的位移量为4×2×i字节;而*(a+i)的基类型为int,j的位移量仍为2×j字节。

 

在(4)中,*(a+i)外的一对圆括号不可少,若写成:*(a+i)[j],因为运算符[]的优先级高于*号,表达式可转换成:*(*(a+i)+j)),即为:*(*(a+i+j)),这时i+j将使得位移量为4×2×(i+j)个字节,显示然这已不是元素a[i][j]的地址。*(*(a+i+j))等价于*(a[i+j])、等价于:a[i+j][0],引用的是数组元素a[i+j][0],而不是a[i][j],很可能早已超出数组定义的范围。

 

在(5)中,&a[0][0]+4*i+j代表了数组元素a[i][j]的地址,通过间址运算符*号,表达式*(&a[0][0]+4*i+j)代表了数组元素a[i][j]的存储单元。

 

3、通过建立一个指针数组来引用二维数组元素若有以下定义:int *p[3], a[3][2], i,j ;在这里,说明符*p[3]中,也遵照运算符的优先级,一对[]的优先级高于*号,因此p首先与[]结合,构成p[3],说明了p是一个数组名,系统将为它开辟3个连续的存储单元;在它前面的*号则说明了数组p是指针类型,它的每个元素都是基类型为int的指针。若满足条件:0≤i<3,则p[i]和a[i]的基类型相同,p[i]= a[i]是合法的赋值表达式。

 

若有以下循环:for(i=0; i<3; i++) p[i]= a[i];在这里,赋值号右边的a[i]是常量,表示a数组每行的首地址,赋值号左边的p[i]是指针变量,循环执行的结果使p[0]、p[1]、p[2]分别指向a数组每行的开头。这时,数组p和数组a之间的关系如图9.6所示。

 

当p数组的每个元素已如图9.6所示指向a数组每行的开头时,则a数组元素a[i][j]的引用形式*(a[i]+ j)和*(p[i]+j)是完全等价的。由此可见,这时可以通过指针数组p来引用a数组元素,它们的等价形式如下:(1)*(p[i]+j) (2)*(*(p+i)+j) (3)(*(p+i))[j] (4)p[i][j] 不同的是:p[i]中的值是可变的,而a[i]中的值是不可变的。

 

 图9.64、通过建立一个行指针来引用二维数组元素若有以下定义:int a[3][2], (*prt)[2];在这里,说明符(*prt)[2]中,由于一对圆括号的存在,所以*号首先与prt结合,说明prt是一个指针变量,然后再与说明符[2]结合,说明指针变量prt的基类型是一个包含有两个int元素的数组。在这里,prt的基类型与a的相同,因此prt=a;是合法的赋值语句。prt+1等价于a+1、等价于a[1]。当prt指向a数组的开头时,可以通过以下形式来引用a[i][j]:(1) *(prt[i]+j) (2) *(*(prt+i)+j) (3)(*(prt+i))[j] (4) prt[i][j] 在这里,prt是个指针变量,它的值可变,而a是一个常量。

 

 

附:

#include "stdio.h"
void disp(int (*a)[3])
{
    printf("%d",*(*(a+1)+1));
}

void main()
{
    int a[2][3];
    a[0][0]=1;
    a[0][1]=2;
    a[0][2]=3;
    a[1][0]=4;
    a[1][1]=5;
    a[1][2]=6;
    disp(&a[0]);//也可以写作disp(a);
}

这是我收藏的一篇博文,希望对你有用!

因为有了因为,所以有了所以,既然已成既然,何必再说何必
2011-02-27 15:18
林浩
Rank: 2
等 级:论坛游民
帖 子:47
专家分:23
注 册:2011-1-12
收藏
得分:0 
回复 2楼 cacker
那我把p=a改成p=*a可以不呢
2011-02-27 16:11
cacker
该用户已被删除
收藏
得分:5 
提示: 作者被禁止或删除 内容自动屏蔽
2011-02-27 16:23
快速回复:有关指针指向二维数组的小插曲,求个小问?(需要详解)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.037534 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved