以下是引用默默学习在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 编辑 ]