| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1100 人关注过本帖
标题:指针数组行参问题,求解。主函数输出地址,调用函数就输出内容,为什么呢!!
只看楼主 加入收藏
默默学习
Rank: 4
等 级:业余侠客
帖 子:134
专家分:200
注 册:2010-6-22
结帖率:84.21%
收藏
已结贴  问题点数:20 回复次数:6 
指针数组行参问题,求解。主函数输出地址,调用函数就输出内容,为什么呢!!
#include "stdio.h"
int sort(int *sp[2]);
void main()
{
    int p[3][2]={{48,12},{22,54},{6,18}};
    int *sp[]={p};
    sort(p);
    printf("主函数指针数组:%d   ",sp[0]);
    printf("主函数为什么取的是指针数组的首地址.\n\n");
}
int sort(int *sp[])
{
    printf("子函数指针数组:%d ",sp[0]);
    printf("   子函数直接输出了结果?,.\n");
}
//我是这样理解的: 主函数中 **sp输出了结果48.
//那么相同的,子函数中 *sp应该也是首指针地址,而后**sp才应该是结果呀。
//为什么子函数直接输出结果了呢?难道是因为它*sp[1]={p};sp就直接是p的地址了吗?,但主函数中sp应该是表示指针数组的元素地址才对呀。

[ 本帖最后由 默默学习 于 2011-3-3 23:06 编辑 ]
搜索更多相关主题的帖子: include 
2011-03-03 22:55
qq1023569223
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:湖南科技大学
等 级:贵宾
威 望:26
帖 子:2753
专家分:13404
注 册:2010-12-22
收藏
得分:0 
我的是直接编译出错,运行不出来!至于你说的,我还真不知道!

   唯实惟新 至诚致志
2011-03-04 09:06
犬虫门心
Rank: 8Rank: 8
来 自:西安
等 级:蝙蝠侠
帖 子:209
专家分:753
注 册:2011-1-25
收藏
得分:0 
以下是引用默默学习在2011-3-3 22:55:23的发言:

#include "stdio.h"
int sort(int *sp[2]);
void main()
{
    int p[3][2]={{48,12},{22,54},{6,18}};
    int *sp[]={p};
    sort(p);
    printf("主函数指针数组:%d   ",sp[0]);
    printf("主函数为什么取的是指针数组的首地址.\n\n");
}
int sort(int *sp[])
{
    printf("子函数指针数组:%d ",sp[0]);
    printf("   子函数直接输出了结果?,.\n");
}
//我是这样理解的: 主函数中 **sp输出了结果48.
//那么相同的,子函数中 *sp应该也是首指针地址,而后**sp才应该是结果呀。
//为什么子函数直接输出结果了呢?难道是因为它*sp[1]={p};sp就直接是p的地址了吗?,但主函数中sp应该是表示指针数组的元素地址才对呀。

楼主,你发给我的消息已经收到,看到你的帖子,想想还是在这里说好些。
int *sp[]={p};这种写法我还是第一次见到,虽然明显是错误的,但我还是上机验证了一下。编译系统提示警告。
先说int p[3][2];这是一个二维数组,其中数组名称p,在我的看法中,其实它是一个行指针。下面我说明一下:
在定义语句int p[3][2];中,有两个[],其中[3]距离p最近,它和p结合最紧密,[2]和p的关系相对疏松。
那么,可以把[2]与int放在一起,构成:int[2]     p[3];
注意,这个写法C当然不能识别(不过在Java中,这是常见的形式),这样只是为了便于“理解”。如果把int[2]用符号T(表示任意数据类型类型)替代,那么,上式可看成:
T p[3];
看这个定义语句可以很清晰的知道,p是一个一维数组,它有3个元素,每个元素是T类型的。
而T是int[2];所以数组p的每个元素是一个“由2个int组成的8字节(设在32位系统中)的连续存储空间”;
T p[3];这样看,p实际上就是一个一维数组,p的值就是p[3]中的第一个元素的首地址;更重要的是,p+1应该是它的第二个元素的首地址!
由于p的每个元素都是8B的,那么p+1实际上是移动了“一行”。
所以,p本质上是一个“行指针”,不过它是一个常量,只能使用,不能赋值。

上面的话,请楼主仔细阅读,弄清其中的逻辑关系。在明确了二维数组名称(注意,我并没有说二维数组)的本质是“行指针常量”后,楼主的问题就很清楚了。

    int *sp[]={p};这是错误的。原因如下:
int *sp[] = {p}; <=> int *sp[1] = {p};
怎么理解这种写法的意义呢?是这样的:
在上述的定义语句中,有两个符号:*和[]。由于[]比*优先级高,所以[]与sp结合得更紧密,所以上式还可以等价:
int *sp[1] <=> int*          sp[1];在设int*为T,
T sp[1];
这个定义语句是说:定义了一个一维数组,有1个元素,每个元素的类型是T,就是int *!
但是p是一个行指针(所谓的二级指针),这当然不能和一级指针相提并论。
也就是说,不能用p给数组int *sp[]赋初值。

最后,下面的形参与实参的写法是矛盾的。
int sort(int *sp[2]);
int sort(int *sp[])



sort(p);
前面说过,p的仅从类型说,其实就是int (*)[2];(这种写法完全可以出现在函数的声明中)
而在形参的表达中,int *sp[2] <=> int *sp[] <=> int **sp <=> int*    *sp
从最右边的写法中可以知道,如果对sp+1将移动sizeof(int*)个字节,即4B,这和p+1将移动8B相矛盾。
应该这样写:
int sort(int (*)[2]); //这是声明
int sort(int (*sp)[2]) //这是定义。注意,这里的[2]绝对不能缺省。
{}

[ 本帖最后由 犬虫门心 于 2011-3-4 11:08 编辑 ]

当一名对得起学生学费的老师,一直是我的目标!我会更努力的!
2011-03-04 10:37
默默学习
Rank: 4
等 级:业余侠客
帖 子:134
专家分:200
注 册:2010-6-22
收藏
得分:0 
首先第一句是想对你说声:谢谢.
我看了您的回答。你强调要我了解的是 二维数组名称,还有指向它的数组指针,.其实我是想尝试一下指针数组指向的问题。
比如: int p[3][2]={{48,12},{22,54},{6,18}};
       用指针数组的话,它是指针连续存放的数组.每个一个数组元素指针都可以指向一个元素的地址,对吗?
所以我这样理解:定义 int *Sp[2]={p,p[2]}; 建立一个指针数组,它有两个指针,我让p[0]第1个元素指针指向 二维数组首地址p,
               那么p既然是二维数组名称,就应该存在一个 *Sp 表示了 p[0] 首地址.,相当于Sp[0]---p ,  Sp[1]---p[2]对吧!
               所以*Sp[0]输出48.问题就在这里了,我如果用子函数来当指针数组的行参呢,那么又应该是怎么赋值跟引用的呢。
所以我不是很理解,指针数组既然可以编译通过行参,那么它又是怎么引用输出的,怎么sp[0]就直接把结果输出了。。希望老师多包涵,
小弟初学有很多不懂的地方..还望多多指教!
2011-03-04 11:39
默默学习
Rank: 4
等 级:业余侠客
帖 子:134
专家分:200
注 册:2010-6-22
收藏
得分:0 
回复 3楼 犬虫门心
麻烦老师了!
2011-03-04 11:43
犬虫门心
Rank: 8Rank: 8
来 自:西安
等 级:蝙蝠侠
帖 子:209
专家分:753
注 册:2011-1-25
收藏
得分:20 
以下是引用默默学习在2011-3-4 11:39:17的发言:

首先第一句是想对你说声:谢谢.
我看了您的回答。你强调要我了解的是 二维数组名称,还有指向它的数组指针,.其实我是想尝试一下指针数组指向的问题。
比如: int p[3][2]={{48,12},{22,54},{6,18}};
       用指针数组的话,它是指针连续存放的数组.每个一个数组元素指针都可以指向一个元素的地址,对吗?
所以我这样理解:定义 int *Sp[2]={p,p[2]}; 建立一个指针数组,它有两个指针,我让p[0]第1个元素指针指向 二维数组首地址p,
               那么p既然是二维数组名称,就应该存在一个 *Sp 表示了 p[0] 首地址.,相当于Sp[0]---p ,  Sp[1]---p[2]对吧!
               所以*Sp[0]输出48.问题就在这里了,我如果用子函数来当指针数组的行参呢,那么又应该是怎么赋值跟引用的呢。
所以我不是很理解,指针数组既然可以编译通过行参,那么它又是怎么引用输出的,怎么sp[0]就直接把结果输出了。。希望老师多包涵,
小弟初学有很多不懂的地方..还望多多指教!
int *sp[2] = {p, p[2]};的写法有问题,应该改成:int *sp[2] = {p[0], p[1]};
在指针的概念中,有一个特别重要的等价式子:
p[i] <=> *(p+i)
设有数组:
int p[3][2];
那么:
第一行第一个元素的首地址:&p[0][0] <=> &(*p[0] + ) <=> p[0]
第二行第一个元素的首地址:&p[1][0] <=> &(*p[1] + ) <=> p[1]
另外:sizeof(p) => 24B,这应该是没有问题的吧,但这说明,数组(含任意维)所申请的空间,除了多个实实在在的最终的元素外,再也没有任何多余的空间存储其它内容了。所以,我会得到数组名称是首地址常量的概念。
这是第一个问题。

第二个问题。
对于二维数组,确实可以用指针数组来引用。比如:
int ar[3][2], *p[3];
再进行下面的多次赋值
int i;
for(i = 0; i < 3; i++)
    p[i] = ar[i];
以后,p[i][j] <=> ar[i][j]

但是,作为参数传递,就要如此:
函数声明:
void fun(int **ap, int m, int n); <=> void fun(int *ap[], int m, int n); <=> void fun(int *ap[3], int m, int n);

void fun(int **ap, int m, int n)
{
    int i, j;

    for(i = 0; i < m; i++)
        for(j = 0; j < n; j++)
            ...ap[i][j]... //对ap[i][j]进行引用的意思
}
而函数的调用要这样:
(设在某函数中)
{
    int ar[3][2], *p[3];
    int i;

    for(i = 0; i < 3; i++)
        p[i] = ar[i];

    fun(p, 3, 2);
    ...
}

请注意,你的程序在编译时是存在警告的,对否?
所以,输出48的情况是不正常的,因为指针的类型已经被你的形参和实参之间的关系改乱了。

[ 本帖最后由 犬虫门心 于 2011-3-4 14:21 编辑 ]

当一名对得起学生学费的老师,一直是我的目标!我会更努力的!
2011-03-04 14:16
默默学习
Rank: 4
等 级:业余侠客
帖 子:134
专家分:200
注 册:2010-6-22
收藏
得分:0 
回复 6楼 犬虫门心
#include "stdio.h"
int sort(int *sp[],int m,int n);
void main()
{
    int p[3][2]={{48,12},{22,54},{6,18}};
    int *sp[3]={p[0],p[1],p[2]};
    sort(sp,3,2);

}
int sort(int *sp[],int m,int n)
{
    int i, j;
     for(i = 0; i < m; i++)
        for(j = 0; j < n; j++)
           printf("%d ",sp[i][j]);
}
受教了,谢谢老师。。
测试后程序无错误提示和警告,编译成功。谢谢拉!
2011-03-04 19:25
快速回复:指针数组行参问题,求解。主函数输出地址,调用函数就输出内容,为什么呢 ...
数据加载中...
 
   



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

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