指针参数

4.6.2.2 无法把指针变量本身传递给一个函数

这很像孙悟空拔下一根猴毛变成自己的样子去忽悠小妖怪。所以fun 函数实际运行时,用到的都是_p2 这个变量而非p2 本身。如此,我们看下面的例子:

void GetMemorychar * p, int num

{

p = (char *)malloc(num*sizeof(char));

}

intmain()

{

char *str = NULL;

GetMemorystr10;

strcpy(str,”hello”);

freestr);//free 并没有起作用,内存泄漏

return 0;

}

在运行strcpy(str,”hello”)语句的时候发生错误。这时候观察str 的值,发现仍然为NULL。也就是说str 本身并没有改变,我们malloc 的内存的地址并没有赋给str,而是赋给了_str。而这个_str 是编译器自动分配和回收的,我们根本就无法使用。所以想这样获取一块内存是不行的。那怎么办? 两个办法:

第一:用return

char * GetMemorychar * p, int num

{

p = (char *)malloc(num*sizeof(char));

return p

}

intmain()

{

char *str = NULL;

str = GetMemorystr10;

strcpy(str,”hello”);

freestr);

return 0;

}

这个方法简单,容易理解。

第二:用二级指针。

void GetMemorychar ** p, int num

{

*p = (char *)malloc(num*sizeof(char));

return p

}

intmain()

{

char *str = NULL;

GetMemory&str10;

strcpy(str,”hello”);

freestr);

return 0;

}

注意,这里的参数是&str 而非str。这样的话传递过去的是str 的地址,是一个值。在函数内部,用钥匙(“*”)来开锁:*(&str),其值就是str。所以malloc 分配的内存地址是真正赋值给了str 本身。

另外关于malloc free 的具体用法,内存管理那章有详细讨论。

4.6.3 二维数组参数与二维指针参数

前面详细分析了二维数组与二维指针,那它们作为参数时与不作为参数时又有什么区别呢?看例子:

void funchar a[3][4];

我们按照上面的分析,完全可以把a[3][4]理解为一个一维数组a[3],其每个元素都是一个含有4 char 类型数据的数组。上面的规则,“C 语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。”在这里同样适用,也就是说我们可以把这个函数声明改写为:

void funchar (*p)[4];

这里的括号绝对不能省略,这样才能保证编译器把p 解析为一个指向包含4 char 类型数据元素的数组,即一维数组a[3]的元素。

同样,作为参数时,一维数组“[]”号内的数字完全可以省略:

void funchar a[ ][4];

不过第二维的维数却不可省略,想想为什么不可以省略?

注意:如果把上面提到的声明void funchar (*p)[4])中的括号去掉之后,声明“void f unchar *p[4])”可以改写成:

void funchar **p;

这是因为参数*p[4],对于p 来说,它是一个包含4 个指针的一维数组,同样把这个一维数组也改写为指针的形式,那就得到上面的写法。

上面讨论了这么多,那我们把二维数组参数和二维指针参数的等效关系整理一下:

这里需要注意的是:C 语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。这条规则并不是递归的,也就是说只有一维数组才是如此,当数组超过一维时,将第一维改写为指向数组首元素首地址的指针之后,后面的维再也不可改写。比如:a[3][4][5]作为参数时可以被改写为(*p[4][5]。至于超过二维的数组和超过二级的指针,由于本身很少使用,而且按照上面的分析方法也能很好的理解,这里就不再详细讨论。有兴趣的可以好好研究研究。

 

 

转自:陈正冲  《语言深度解剖

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值