6304|16

7815

帖子

57

TA的资源

裸片初长成(中级)

楼主
 

【辛版的小编程题】指针作为参数传递? [复制链接]

 
本帖最后由 辛昕 于 2018-3-30 02:11 编辑

这个小小的编程题,答案很简单。
但是,它背后引发出来的一句简短结论,却很值得玩味——

以指针(地址)的形式传递形参,形参可以被修改。
那么问题来了,如果要修改的就是指针的值呢?
那——自然就要传入 指针的 指针(地址)了。


很多时候,由于大多数语言的函数只能至多返回一个返回值(Go除外)。
所以我们经常会把想返回的多几个变量,放在形参里。
这就引发一个问题。
我们太过于熟悉 把地址传入形参,就可以修改该地址指向的内容 这个常识。
由于传递形参时,作为地址传递 和 指针 长得太像。
所以包括我在内,相信绝大多数人都下意识 把 指针 和 地址等同起来。
于是,当有一天我们要修改的是 指针本身的时候,就往往很难想起来
这次要传递的是 指针的指针(二级指针)了。


楼下这段代码,是我最近写的一个EGE上的小函数,用来支持图片不同颜色格式的兼容。
这个函数的用意简单解释如下:
      图像文件以数组形式给出,最后因为不同的RGB位数,它们在逐点取的时候,偏移的量是不同的,
RGB16是2字节,RGB24是3字节,RGBA24是4字节。
      下面这个函数,为了传递出下一个读取的位置,又因为返回值已经被占用,因此,把返回的下一个
图像数组的位置以形参的形式传递。
  1. color_t get_pixel_color(uint8_t *pSrc,uint8_t *pNext)
  2. {
  3.     uint8_t *p;

  4.     if(ColorType == RGB32)
  5.     {
  6.         p = pSrc;
  7.         pNext = pSrc + 4;
  8.         return (EGERGB(*p,*(p + 1),*(p + 2) ) );
  9.     }
  10.     else if(ColorType == RGB24)
  11.     {
  12.         p = pSrc;
  13.         pNext = pSrc + 3;
  14.         return (EGERGB(*p,*(p + 1),*(p + 2) ) );
  15.     }
  16.     else if(ColorType == RGB16)
  17.     {
  18.         uint16_t rgb16;
  19.         rgb16 = *(uint16_t *)pSrc;
  20.         pNext = pSrc + 2;
  21.         return rgb162color(rgb16);
  22.     }
  23.     else
  24.         return (EGERGB(0,0,0) );    // 非支持格式,输出全黑以示错误
  25. }
复制代码


这个函数里使用了一个特定的图形函数库 EGE,所以对于一些非标ANSI的定义和宏,请
直接忽略,它们一点都不影响这个问题本身。

最新回复

因为我只是看见了你函数的代码,不知道你在函数外面是怎么用这个函数的,但是我猜你的程序应该是定义了两个指针变量(就是赋给你函数的两个形参的实参),我写的例子里直接取数组元素的地址和下标,是为了少定义一个指针变量,省去调用函数之后把下一个地址的指针的值赋给当前地址指针。当然这是在C代码中是这样的,编译之后是简单了还是麻烦了就不知道了,水平有限看不懂汇编。总结一下我的想法就是想简化一下调用函数的代码,执行效率有没有增加就不知道了,当然我希望是能增加的,但是不知道怎么查看,有了解的高手可以指点一下。  详情 回复 发表于 2017-12-12 08:55
点赞 关注(1)
个人签名

强者为尊,弱者,死无葬身之地


回复
举报

7815

帖子

57

TA的资源

裸片初长成(中级)

沙发
 
然而,上面这个函数虽然可以通过编译,但是,它实际运行时,不仅无法实现原来的意图。
甚至会导致数组越界死机。

就当这是个小编程题。其实不难很简单,但是一个相当不容易注意的地方。
我写这个函数一开始就是这样实现。
直到出错后,我离开电脑前去洗澡时,才想到问题出在哪。

继而我想到这个问题,其实我不止一次犯过,所以,我特地拿出来,
给大家解解闷。

最先给出正确答案的——
简要说明原因并且在这个函数基础上改成正确的,发帖即可。
版主私人转给100芯币。
 
个人签名

强者为尊,弱者,死无葬身之地

 

回复

767

帖子

2

TA的资源

纯净的硅(初级)

板凳
 
占楼坐等第一个赚100芯币的小伙伴
 
个人签名物致DIY 欢迎你的加入~
QQ群:646461928 公众号:智物知心致成
小店
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

4
 
皈依 发表于 2017-12-10 22:27
占楼坐等第一个赚100芯币的小伙伴

 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

1461

帖子

1

TA的资源

纯净的硅(中级)

5
 
坐等第一个改正的小伙伴
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

6
 
楼主写的这个函数应该是在一个循环里不断读取文件图像数组吧。同时这个函数可以进行三种偏移:2,3,4字节。我猜发生数组越界是因为你的循环次数*4大于了你定义的数组长度了。也许应该在函数里加一个计数器记下你偏移多少了,防止发生越界。等待楼主的正确答案了。
 
 
 

回复

6040

帖子

195

TA的资源

版主

7
 
uint8_t **pNext
 
 
 

回复

1976

帖子

0

TA的资源

五彩晶圆(初级)

8
 
rgb16 = *(uint16_t *)pSrc;pSrc在定义的时候未半字对齐,访问出错?
 
 
 

回复

120

帖子

0

TA的资源

一粒金砂(中级)

9
 
7楼正解,只改了形参的值
 
 
 

回复

172

帖子

0

TA的资源

一粒金砂(中级)

10
 

你的答案应该是正确的。
 
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

11
 

漂亮
就是这样。
100芯币归你了
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

12
 
本帖最后由 hljjxzhla 于 2017-12-11 18:29 编辑
辛昕 发表于 2017-12-11 10:17
漂亮
就是这样。
100芯币归你了

形参该为uint8_t **pNext之后,你函数里使用的时候应该是用*pNext吧。我简化了你的函数功能写了个小例子,感觉应该也能实现你想要的结果,希望能讨论一下。
  • int test(int *present,int *next)
  • {
  •     *next+=4;
  •     return (*present+*(present+1)+*(present+2)+*(present+3));
  • }
  • int main(void)
  • {
  •     int i=0;
  •     int a1[3];
  •     const int a[12]={1,2,3,4,5,6,7,8,9,10,11,12};
  •     for(i=0;i<3;i++)
  •     {
  •         static int n=0;
  •         a1 [ i ]=test(&a[n],&n);
  •         printf("%d ",a1 [ i ]);
  •     }
  •     printf("\n");
  •     return 0;
  • }


 
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

13
 
hljjxzhla 发表于 2017-12-11 08:36
楼主写的这个函数应该是在一个循环里不断读取文件图像数组吧。同时这个函数可以进行三种偏移:2,3,4字节 ...

这也是对的。
崩掉只是一个与主题无关的小失误,我回忆了一下,大概就是这样子。
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

14
 
hljjxzhla 发表于 2017-12-11 18:24
形参该为uint8_t **pNext之后,你函数里使用的时候应该是用*pNext吧。我简化了你的函数功能写了个小例子 ...

我不是很理解你这个实现的意义,想做什么?
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

15
 
辛昕 发表于 2017-12-11 23:10
我不是很理解你这个实现的意义,想做什么?

因为我只是看见了你函数的代码,不知道你在函数外面是怎么用这个函数的,但是我猜你的程序应该是定义了两个指针变量(就是赋给你函数的两个形参的实参),我写的例子里直接取数组元素的地址和下标,是为了少定义一个指针变量,省去调用函数之后把下一个地址的指针的值赋给当前地址指针。当然这是在C代码中是这样的,编译之后是简单了还是麻烦了就不知道了,水平有限看不懂汇编。总结一下我的想法就是想简化一下调用函数的代码,执行效率有没有增加就不知道了,当然我希望是能增加的,但是不知道怎么查看,有了解的高手可以指点一下。
 
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

16
 
hljjxzhla 发表于 2017-12-12 08:55
因为我只是看见了你函数的代码,不知道你在函数外面是怎么用这个函数的,但是我猜你的程序应该是定义了两 ...

哦,我是这样调用的。

get_pixel_color(pimg,&pimg);

在同一副图像上移动指针。
也就是移到下一个像素
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

17
 
hljjxzhla 发表于 2017-12-12 08:55
因为我只是看见了你函数的代码,不知道你在函数外面是怎么用这个函数的,但是我猜你的程序应该是定义了两 ...

我很少看汇编。
又不是优化,没到那一步。
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表