一个按比特位拷贝数据的函数copybits

本文介绍了一个用于按比特位高效拷贝数据的算法,并提供了代码实现。通过优化源和目标开始位置为2的整数倍,提高数据拷贝效率。

一个按比特位拷贝数据的函数

没有进行特别的优化。其实还可以在拷贝源开始位置和目标开始位置是2的整数倍位置的时候进行优化。

说明

这个函数用于从src数组首地址跳过sbb个字节,又跳过ssb个比特位,拷贝nbits个比特位的数据到dest数组首地址跳过dbb个字节,又跳过dsb个比特位位置。

代码如下

  1 include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <assert.h>
  5 
  6 //二进制打印输出
  7 void Bp(unsigned char n)  
  8 {  
  9   int i;
 10   for (i=7;i>=0;i--)  
 11   {  
 12     printf("%u",(n>>i)&1);  
 13   }
 14 }
 15 
 16 //按比特位拷贝
 17 // 从src数组首地址跳过sbb个字节,又跳过ssb个比特位,拷贝nbits个比特位的数据到
 18 //   dest数组首地址跳过dbb个字节,又跳过dsb个比特位位置
 19 int copybits(const unsigned char* src,int sbb/*source begin byte*/,int ssb/*source skip bit*/,
 20       unsigned char* dest,int dbb/*dest begin byte*/,int dsb/*dest skip bit*/,int nbits)
 21 {
 22   // assert(src && dest && sbb>=0 && ssb>=0 && dbb>=0 && dsb>=0 && nbits>=0);
 23   if(src ==NULL || dest == NULL)return -1;
 24   if(sbb < 0 || ssb < 0 || dbb < 0 || dsb <0)return -2;
 25   if(nbits==0)return 0;
 26 
 27   if(ssb == dsb){
 28     //边界对其情况
 29     //1拷贝对齐部分
 30     int copybyte=(nbits -(8-ssb))/8;
 31     memmove(dest+dbb+1,src+sbb+1,copybyte);
 32     //2拷贝前端不完整字节
 33     if(ssb != 0){
 34       unsigned char s=src[sbb];
 35       s &= 0xFF>>ssb;
 36       dest[dbb] &= 0xFF<<(8-ssb);
 37       dest[dbb] |= s;
 38     }
 39     //拷贝后端不完整字节
 40     int endbit=(nbits - (8- ssb))%8;
 41     if(endbit != 0){
 42       unsigned char s=src[sbb+1+copybyte];
 43       s &= 0xFF<<(8-endbit);
 44       dest[dbb+1 + copybyte] &= 0xFF>>endbit;
 45       dest[dbb+1 + copybyte] |= s;  
 46     }
 47     return (8 - endbit);
 48   }
 49   //-------------------------------------------------
 50 
 51   int sbgb = sbb*8 + ssb;  //源开始的比特位置
 52   int dbgb = dbb*8 + dsb;  //目标开始比特位置
 53   int i,ret;
 54   int k1,m1,k2,m2;
 55   unsigned char s;
 56   if(((dest - src)*8+dbgb) < sbgb  ){
 57     // 目标开始位置在源开始位置左边
 58     for(i=0;i<nbits;++i){
 59       //拷贝某个位
 60       //1、源位置      目标位置
 61       k1=(sbgb+i)>>3;    k2=(dbgb+i)>>3;
 62       m1=(sbgb+i)&0x7;  m2=(dbgb+i)&0x7;
 63       s=src[k1];
 64       s &= 0x80>>m1;  //获取源比特位
 65       if(m1!=m2){  //偏移位
 66         s = m1<m2? (s>>(m2-m1)):(s<<(m1-m2));
 67       }
 68       dest[k2] &= (~(0x80>>m2));  //目标位置0
 69       dest[k2] |= s;  //目标位赋值
 70     }
 71   }
 72   else{
 73     for(i=nbits-1; i >=0 ;--i){
 74       //拷贝某个位
 75       //1、源位置      目标位置
 76       k1=(sbgb+i)>>3;    k2=(dbgb+i)>>3;
 77       m1=(sbgb+i)&0x7;  m2=(dbgb+i)&0x7;
 78       s=src[k1];
 79       s &= 0x80>>m1;  //获取源比特位
 80       if(m1!=m2){  //偏移位
 81         s = m1<m2? (s>>(m2-m1)):(s<<(m1-m2));
 82       }
 83       dest[k2] &= (~(0x80>>m2));  //目标位置0
 84       dest[k2] |= s;  //目标位赋值
 85     }
 86 
 87   }
 88   return (8 - (dbgb+nbits)%8);
 89 }
 90 
 91 
 92 
 93 
 94 int main()
 95 {
 96   int i;
 97   unsigned char src[10]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//{0,0x1F,0x0F,0x0F,0x70,0,0,1,1};
 98   unsigned char dst[10]={0,0,0,0,0,0,0,0,0};
 99 
100   printf("%d\n",copybits(src,1,3,dst,0,5,24));
101 
102   for(i=0;i<10;++i){
103     //printf("\t%2x\t%2x\n",src[i],dst[i]);
104     Bp(src[i]);
105     putchar(' ');
106   }
107   putchar('\n');
108   for(i=0;i<10;++i){
109     //printf("\t%2x\t%2x\n",src[i],dst[i]);
110     Bp(dst[i]);
111     putchar(' ');
112   }
113   putchar('\n');
114   return 0;
115 }

 

 

<think>我们正在讨论C语言中的memcpy函数。用户询问memcpy是按位拷贝还是按字节拷贝。首先,我需要明确memcpy的工作原理。 根据C语言标准,memcpy函数用于复制内存块的内容,它是以字节为单位进行拷贝的。函数的原型是: void *memcpy(void *dest, const void *src, size_t n); 其中,n参数指定了要拷贝的字节数。 因此,memcpy每次拷贝的最小单位是一个字节,而不是一位(bit)。 同时,需要注意的是,memcpy只是简单地按字节复制内存内容,它不关心数据的类型或结构,也不关心内存是否重叠(如果内存重叠,应该使用memmove函数)。 我们可以通过一个简单的例子来说明:假设我们有一个int类型的数组,我们想复制其中的一部分,memcpy会根据指定的字节数来复制,而不会关心int的位数(即不会按位复制)。 例如,在32位系统中,一个int通常是4个字节,那么复制一个int就是复制4个字节;复制10个int就是复制40个字节。 所以,答案是按字节拷贝。 接下来,为了帮助用户理解,我们可以举一个例子: 假设有以下代码: char src[] = "Hello, world!"; char dest[20]; memcpy(dest, src, strlen(src)+1); // 这里复制了strlen(src)+1个字节(包括结束符'\0') 在这个例子中,memcpy逐个字节地将src数组的内容复制到dest数组中。 另外,我们还可以提到,由于是按字节拷贝,所以对于非字节对齐的数据,memcpy也可以正常工作(但要注意性能可能受影响,因为某些架构上非对齐访问会降低速度)。 最后,我们可以生成几个相关问题,以帮助用户深入理解。 注意:在回答中,我们不需要使用LaTeX数学公式,因为这是一个编程问题,重点在于解释概念和示例代码。但是,如果涉及到公式,比如计算拷贝的字节数,我们可以使用公式。不过在本问题中,可能不需要。 但是,根据系统级指令,如果出现数学表达式,就要用$...$格式。这里可能不会用到,但如果有,比如提到拷贝数据量是$n$字节,我们就这样写。 现在,我们按照要求来组织回答。 注意:用户提到了“参考站内引用”,但这里我们没有具体的引用来源,所以不需要添加引用标识。但如果有引用,比如参考了C语言标准文档,则可以添加。 由于这是一个常见问题,我们可以根据标准知识回答。 因此,回答的结构如下: 1. 明确回答:是按字节拷贝。 2. 解释memcpy函数的工作原理。 3. 举例说明。 4. 注意事项(如内存重叠问题)。 5. 生成相关问题。 </think>在C语言中,`memcpy`函数是**按字节(byte)拷贝**的,而不是按位(bit拷贝。以下是关键说明: 1. **函数原型**: ```c void *memcpy(void *dest, const void *src, size_t n); ``` 参数`n`明确指定要拷贝的**字节数**,例如`memcpy(dest, src, 10)`表示拷贝10个字节。 2. **最小单位是字节**: `memcpy`直接操作内存地址,逐字节复制数据。例如拷贝一个`int`变量(通常占4字节)时,会复制连续的4个内存字节,而不关注其内部的二进制位结构[^1]。 3. **与按位拷贝的区别**: - 按位拷贝需操作单个比特(bit),但C语言没有直接操作比特的内存复制函数。 - 按字节拷贝效率更高,因为内存寻址和CPU指令集通常以字节为最小寻址单位。 4. **示例说明**: ```c #include <stdio.h> #include <string.h> int main() { char src[] = {0x12, 0x34}; // 两个字节:00010010 00110100 char dest[2]; memcpy(dest, src, 2); // 按字节复制 // dest内容与src完全相同:0x12, 0x34 return 0; } ``` 5. **注意事项**: - 不检查内存重叠(需用`memmove`处理重叠区域)。 - 不关心数据类型,仅按内存布局直接复制字节序列。 - 拷贝长度必须手动计算为字节数(如`sizeof(int) * n`)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值