Dict.CN 在线词典, 英语学习, 在线翻译
随笔-97  评论-326  文章-0  trackbacks-0

看到一段代码,学习一下:

 1 void* mymemcpy( void* dest, const void* src, size_t count )
 2 {
 3     char* d = (char*)dest;
 4     const char* s = (const char*)src;
 5     int n = count>>3;
 6     switch( count & 7 )
 7     {
 8            case 0:  
 9         do {  
10             *d++ = *s++;
11             case 7:      *d++ = *s++;
12             case 6:        *d++ = *s++;
13             case 5:        *d++ = *s++;
14             case 4:        *d++ = *s++;
15             case 3:        *d++ = *s++;
16             case 2:        *d++ = *s++;
17             case 1:        *d++ = *s++;
18         } while (--> 0);
19     }
20     return dest;
21 }

实际上也可以这么写
 1 void* mymemcpy( void* dest, const void* src, size_t count ) 
 2 
 3     char* d = (char*)dest; 
 4     const char* s = (const char*)src; 
 5   //  int n = (count + 7) / 8; // count > 0 assumed 
 6     int n = count >> 3
 7     switch( count & 7 ) 
 8     { 
 9               do {  *d++ = *s++
10     case 7:        *d++ = *s++
11     case 6:        *d++ = *s++
12     case 5:        *d++ = *s++
13     case 4:        *d++ = *s++
14     case 3:        *d++ = *s++
15     case 2:        *d++ = *s++
16     case 1:        *d++ = *s++
17     case 0          } //while (--n > 0); 
18                  while (n-- > 0
19     } 
20 
21     return dest; 
22 
23 
24 
这么写更容易理解
实际上这里也可以是4个字节来复制,而不是8。其实这个看喜好。
posted on 2006-03-28 22:58 笨笨 阅读(805) 评论(16)  编辑 收藏 引用

评论:
# re: 一段关于memcpy的代码 2006-03-29 09:32 | 虫子
你这个算法只处理了最后一部分数据了吧,前面整8倍数的数据处理了嘛?  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-03-29 10:39 | 笨笨
呵呵,看来你还没有理解这个代码。
我解释一下:
n是我们需要循环的次数,我们的switch中有8个项,所以我们除8。
在count&7这个时候实际上这样的count&0x111,我们仅仅取最低三位,也就是除8的余数,这可以保证,即使count不能被8整除也能处理多余的数据。
好了,现在回到循环,第一轮处理多余的部分(如果有),然后用N来控制循环次数

这里的case语句会从上到下一直执行,因为没有break语句

最终可以保证我们需要的次数  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-03-29 10:41 | 笨笨
实际上这和:
1 void* mymemcpy( void* dest, const void* src, size_t count )
2 {
3 char* d = (char*)dest;
4 const char* s = (const char*)src;
5 do {
*d++ = *s++;
10
18 } while (count -- > 0) ;
20
21 return dest;
22 }
没有本质区别,仅仅循环的次数减少了。
有人说这个提高的效率,不知道提高在什么地方。
另外,我们也可以用4,16等任意数字来代替这里的8,当然以方便处理为依据。  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-03-29 16:48 | 虫子
do{}while();不是应该放在switch外面吗?
  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-03-29 21:29 | 笨笨
不是,是就不对了  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-03-31 13:36 | 芋头
的确是看过这么写的,不过不知道怎么优化的,我觉得应该是效率不高吧。效率高的做法一般是超过一定长度,就选按每4字节整体拷贝,生成的汇编指令一般是rep movl...,剩下几字节单独拷贝。编译器都会特殊处理这个函数。

上面这个代码在我的GCC上用最高的优化方式也不能生成高效代码。  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-04-01 09:46 | 沐枫
个人觉得很难优化。因为每个字节拷贝,都要留一个跳转入口。编译器又怎么敢私自用8字节操作指令直接优化掉它呢。
由此估计,写此代码纯粹是为了挑战C/C++的语法。  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-04-03 15:41 | a1240
我个人感觉,如果没有特殊的要求,还是不要这样写代码为好。毕竟,简单直观的代码才好维护嘛。  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-04-16 17:35 | 请问:
能否解释一下switch语句:
switch( count & 7 ) 8 {
9 do { *d++ = *s++;
10 case 7: *d++ = *s++;
11 case 6: *d++ = *s++;
12 case 5: *d++ = *s++;
13 case 4: *d++ = *s++;
14 case 3: *d++ = *s++;
15 case 2: *d++ = *s++;
16 case 1: *d++ = *s++;
17 case 0 } //while (--n > 0);
18 while (n-- > 0)
19 }
  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-04-16 22:03 | 笨笨
看上面的回复  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-04-19 11:12 | LiLing
这样写是为了提高内存访问效率,各位可以看看计算机组成原理中的内存结构就清楚了。  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-11-15 12:49 | qzq
根本不可能高效,原因有2个:
1. 不算循环,拷贝每个字节,也要2次++,1次拷贝。
2. 用汇编更高效

但没有必要重新发明轮子。
C的库函数或者操作系统的标准函数,如:
CopyMemory ()
memcpy()
这种内存代码你千万不要尝试自己去实现,那将是一种灾难,在每个操作系统/编译器中,内存拷贝可以说是非常频繁的,所以系统/编译器的内存拷贝函数基本上都是非常完美的,VC++用的就是汇编代码,
不信的话你可以自己写一段内存拷贝函数,然后和系统的内存拷贝函数比较一下就知道了。

  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-11-17 09:30 | 笨笨
我从来没有说过这个代码比系统函数高效,我提出来的目的在于和大家一道探讨程序的写法。  回复  更多评论
  
# re: 一段关于memcpy的代码 2006-12-15 10:48 | lwang
楼主第一个程序写错了
应该是n--,不是--n
不信试试下面的代码,结果不对,改成n--就对了。
#include <stdio.h>

void* mymemcpy( void* dest, const void* src, size_t count )
{
char* d = (char*)dest;
const char* s = (const char*)src;
int n = count>>3;
switch( count & 7 )
{
case 0:
do {
*d++ = *s++;
case 7: *d++ = *s++;
case 6: *d++ = *s++;
case 5: *d++ = *s++;
case 4: *d++ = *s++;
case 3: *d++ = *s++;
case 2: *d++ = *s++;
case 1: *d++ = *s++;
} while (--n > 0);
}
return dest;
}
int main()
{
char * src = "hello, world.\n";
char dst[100] = {0};

mymemcpy(dst, src, strlen(src));
printf("src:%sdst:%s", src, dst);
return 0;
}  回复  更多评论
  
# re: 一段关于memcpy的代码 2008-04-21 17:52 | vfdff
switch( count & 7 )
7 {
8 case 0:
9 do {
10 *d++ = *s++;
11 case 7: *d++ = *s++;
12 case 6: *d++ = *s++;
13 case 5: *d++ = *s++;
14 case 4: *d++ = *s++;
15 case 3: *d++ = *s++;
16 case 2: *d++ = *s++;
17 case 1: *d++ = *s++;
18 } while (--n > 0);
19 }
怎么switch语句内部可以有 除了case 之外的语句 *d++ = *s++; 呢 ?  回复  更多评论
  

标题  
姓名  
主页
验证码 *
内容(提交失败后,可以通过“恢复上次提交”恢复刚刚提交的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
[使用Ctrl+Enter键可以直接提交]
相关链接:
网站导航: