OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4787|回复: 5

C语言 内存管理实验mymemcpy()函数,恳请原子哥指教~

[复制链接]

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
发表于 2016-6-15 10:45:46 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 liuchang 于 2016-6-15 10:48 编辑

问题见附件,恳请各位指教~~~
[mw_shl_code=c,true]void mymemcpy(void *des, void *src, u32 n)
{
        u8 *xdes = des;
        u8 *xsrc = src;
        while(n--) *xdes++ = *xsrc++;
};[/mw_shl_code][mw_shl_code=c,true]void mymemcpy(void *des, void *src, u32 n)
{                                                        //上面程序是原子的源码,下面这个是我自己写的
        while(n--) *(u8 *)des++ = *(u8 *)src++;   //小弟不太明白,为什么在源码中需要先申请局部变量,直接操作形参不是更直接,而且代码更加简洁吗?
}                                                        //我看网上也有很多源码也是采用原子的这个形式,小弟实在是想不通,恳请原子哥和各位大神指教~~~[/mw_shl_code]                                 

最佳答案

查看完整内容[请看2#楼]

IAR FOR ARM 6.7 下面这个语句有两个编译错误提示 while(n--) *(u8 *)des++ = *(u8 *)src++; Error: expression must be a pointer to a complete object type Error: expression must be a pointer to a complete object type *(u8 *)des++这里面的 “*” “(u8*)” 和“++”都是相同优先级,自右向左结合,就是说 des先++,然后被强制转换为(u8*)类型,而转化之前的des是void*类型,有的编译器中不能直接进行++操 ...
电子爱好者
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-6-15 10:45:47 | 显示全部楼层
本帖最后由 ianhom 于 2016-6-15 14:31 编辑
liuchang 发表于 2016-6-15 12:40
当然可以,有什么问题吗?

IAR FOR ARM 6.7 下面这个语句有两个编译错误提示

while(n--) *(u8 *)des++ = *(u8 *)src++;

Error[Pe852]: expression must be a pointer to a complete object type
Error[Pe852]: expression must be a pointer to a complete object type

*(u8 *)des++这里面的 “*”  “(u8*)” 和“++”都是相同优先级,自右向左结合,就是说 des先++,然后被强制转换为(u8*)类型,而转化之前的des是void*类型,有的编译器中不能直接进行++操作,就会出现错误expression must be a pointer to a complete object type。
楼主能编译通过,且运行无问题的话,估计是编译器把void* 当做u8*类型处理了。

解决上面的问题可以多加个括号
while(n--) *((u8 *)des)++ = *((u8 *)src)++;
这样确保先把void*类型转换为u8*类型,然后++,可惜遗憾的发现,这样在我的编译环境里还是错误的,报错Error[Pe137]: expression must be a modifiable lvalue,貌似编译器把((u8 *)des)作为常量对待,导致无法进行++操作。可见我的这个编译器并没有那么“灵活”。。。

为了能在我的环境下编译通过,把楼主的两段函数改成这样,void*用u8*类型代替,比较汇编结果
void mymemcpy1(u8 *des, u8 *src, u32 n)
{
    u8 *xdes = des;
    u8 *xsrc = src;                                                   
    while(n--) *xdes++ = *xsrc++;   
}

void mymemcpy2(u8 *des, u8 *src, u32 n)
{                                                   
    while(n--) *des++ = *src++;   
}
在我的编译器在LOW及更高的优化等级下,两段代码的汇编结果是完全一样的。只有在优化等级为NONE时,第一段代码会多一点点。

所以在下不成熟的猜测:两种形式汇编结果基本一致,但写成第一种形式能更好兼容不同的编译器(正如3楼 @myxiaoniao 所说)。
还有很多疑惑,坐等大神补充指正。


机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

3

主题

347

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
2078
金钱
2078
注册时间
2014-12-19
在线时间
710 小时
发表于 2016-6-15 11:59:20 来自手机 | 显示全部楼层
本帖最后由 lvehe 于 2016-6-15 12:15 编辑

你的代码能编译通过吗?
回复

使用道具 举报

3

主题

197

帖子

0

精华

高级会员

Rank: 4

积分
538
金钱
538
注册时间
2012-7-19
在线时间
63 小时
发表于 2016-6-15 12:20:37 | 显示全部楼层
你的代码是依赖于编译器的
回复

使用道具 举报

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
 楼主| 发表于 2016-6-15 12:40:55 | 显示全部楼层
lvehe 发表于 2016-6-15 11:59
你的代码能编译通过吗?

当然可以,有什么问题吗?
电子爱好者
回复

使用道具 举报

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
 楼主| 发表于 2016-6-15 15:39:51 | 显示全部楼层
ianhom 发表于 2016-6-15 12:50
IAR FOR ARM 6.7 下面这个语句有两个编译错误提示

while(n--) *(u8 *)des++ = *(u8 *)src++;

一直蒙受大神指导,不胜感激~
小弟明白了,这里主要的作用是进行变量类型的转换,再次感谢大神~

电子爱好者
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 14:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表