如何在C++中实现按位存取

所属分类: 软件编程 / C 语言 阅读数: 48
收藏 0 赞 0 分享

在我创业的一个项目中,为了节约网络带宽,因此在网络中传输数据需要实现紧凑存取,在国防,科研,航天,军工等多个领域其实也有类似的需求。
实现紧凑存取,不是按一个字节一个字节地存取,而是按位存取。比如一个字节,我们可以存储8个bool信息,废话少说,直接分享代码(备注:里面的代码算法值得优化)。

//以下为函数定义 

/***********************************************************************/ 
/*  函数作用:从buffer读一个位                    */ 
/*  参数pBuffer[in]:指定buffer                    */ 
/*  参数nStart[in]:指定位置                     */ 
/*  参数nEnd[out]:返回结束位置                    */ 
/*  参数retByte[out]:返回读取结果值                 */ 
/*  返回:void                              */ 
/***********************************************************************/ 
void ReadOneBit( byte* pBuffer, int nStart, /* out */int& nEnd, /* out */ byte& retByte ); 
 
/***********************************************************************/ 
/*  函数作用:从指定buffer里读任意一段位置数据            */ 
/*  参数pBuffer[in]:指定buffer                    */ 
/*  参数nStart[in]:指定位置                     */ 
/*  参数btLength[in]:读取长度                    */ 
/*  参数nEnd[out]:返回结束位置                    */ 
/*  参数retData[out]:返回读取结果值,支持任意数据类型        */ 
/*  返回:void                              */ 
/***********************************************************************/ 
template<typename T> 
void ReadDataFromBuffer( byte* pBuffer, int nStart, byte btLength, /* out */int& nEnd, /* out */ T& retData ); 
 
/***********************************************************************/ 
/*  函数作用:从指定buffer里读取一段字符串              */ 
/*  参数pBuffer[in]:指定buffer                    */ 
/*  参数nStart[in]:指定位置                     */ 
/*  参数nCount[in]:字符串长度                    */ 
/*  参数nEnd[out]:返回结束位置                    */ 
/*  参数pRetData[out]:返回读取字符串结果               */ 
/*  返回:void                              */ 
/***********************************************************************/ 
void ReadStringFromBuffer( byte* pBuffer, int nStart, int nCount, /* out */int& nEnd, /* out */char* pRetData ); 
 
 
 
/***********************************************************************/ 
/*  函数作用:向buffer写一个位                    */ 
/*  参数pBuffer[in]:指定buffer                    */ 
/*  参数btData[in]:需要写入的值                   */ 
/*  参数nStart[in]:指定位置                     */ 
/*  参数nEnd[out]:返回结束位置                    */ 
/*  返回:void                              */ 
/***********************************************************************/ 
void WriteOneBit( byte* pBuffer, byte btData, int nStart, /* out */int& nEnd ); 
 
/***********************************************************************/ 
/*  函数作用:向指定buffer里写入任意一段数据             */ 
/*  参数pBuffer[in]:指定buffer                    */ 
/*  参数tData[in]:需要写入的数据,支持任意数据类型          */ 
/*  参数nStart[in]:指定位置                     */ 
/*  参数btLength[in]:读取长度                    */ 
/*  参数nEnd[out]:返回结束位置                    */ 
/*  返回:void                              */ 
/***********************************************************************/ 
template<typename T> 
void WriteDataToBuffer( byte* pBuffer, T tData, int nStart, byte btLength, /* out */int& nEnd ); 
 
/***********************************************************************/ 
/*  函数作用:向指定buffer里写取一段字符串              */ 
/*  参数pBuffer[in]:指定buffer                    */ 
/*  参数pchar[in]:需要写入的字符串                  */ 
/*  参数nStart[in]:指定位置                     */ 
/*  参数nCount[in]:字符串长度                    */ 
/*  参数nEnd[out]:返回结束位置                    */ 
/*  返回:void                              */ 
/***********************************************************************/ 
void WtriteStringToBuffer( byte* pBuffer, char* pchar, int nStart, int nCount, /* out */int& nEnd ); 

//以下为函数实现

void ReadOneBit( byte* pBuffer, int nStart, /* out */int& nEnd, /* out */ byte& retByte ) 
{ 
  byte btData = pBuffer[nStart/8]; 
  btData = btData << nStart%8; 
  retByte = btData >> 7; 
  nEnd = nStart+1; 
} 
 
template<typename T> 
void ReadDataFromBuffer( byte* pBuffer, int nStart, byte btLength, /* out */int& nEnd, /* out */ T& retData ) 
{ 
  //顺序读位 
  retData = 0; 
  if ( btLength > sizeof(T)*8 ) 
    return ; 
   
  byte btData; 
  T tData; 
  while ( btLength-- ) 
  { 
    ReadOneBit(pBuffer, nStart, nStart, btData); 
    tData = btData << btLength; 
    retData |= tData; 
  } 
   
  nEnd = nStart; 
} 
 
void ReadStringFromBuffer( byte* pBuffer, int nStart, int nCount, /* out */int& nEnd, /* out */char* pRetData ) 
{ 
  for ( int nIndex=0; nIndex<nCount; nIndex++ ) 
  { 
    ReadDataFromBuffer(pBuffer, nStart, 8, nStart, pRetData[nIndex]); 
  } 
  nEnd = nStart; 
} 
 
 
void WriteOneBit( byte* pBuffer, byte btData, int nStart, /* out */int& nEnd ) 
{ 
  int nSet = nStart / 8; 
  byte c = pBuffer[nSet]; 
  switch ( btData ) 
  { 
  case 1: 
    c |= ( 1 << (7- nStart % 8) ); 
    break; 
  case 0: 
    c &= ( ~(1 << (7- nStart % 8) ) ); 
    break; 
  default: 
    return; 
  } 
  pBuffer [nSet] = c; 
  nEnd = nStart +1; 
} 
 
 
 
template<typename T> 
void WriteDataToBuffer( byte* pBuffer, T tData, int nStart, byte btLength, /* out */int& nEnd ) 
{ 
/* //大端机模式 
  byte btDataLength = sizeof(T); 
  if ( btLength > sizeof(T)*8 ) 
    return; 
   
  int nDataStart = 0; //数据的第一位位置为0,顺序写入 
  while ( btLength-- ) 
  { 
    byte bitData; 
    ReadOneBit((byte*)&tData, nDataStart, nDataStart, bitData); 
    WriteOneBit(pBuffer, bitData, nStart, nStart); 
  } 
   
  nEnd = nStart; 
*/ 
 
  //小端机模式:写buffer的时候,不能顺序写位 
 
  //获得模版占用字节大小 
  byte btDataLength = sizeof(T); 
 
  //校验长度是否越界 
  if ( btLength > sizeof(T)*8 ) 
    return; 
 
  //将待写数据转为byte* 
  byte* ptData = (byte*)&tData;  
 
  //求模与余 
  int nSet = btLength / 8; 
  int nRin = btLength % 8; 
   
  //定义字节数据与位数据 
  byte bitData; 
  byte byteData; 
  int nTempEnd; 
 
  //先写rin数据 
  byteData = ptData[nSet]; 
  while ( nRin-- ) 
  { 
    ReadOneBit(&byteData, 7-nRin, nTempEnd, bitData); 
    WriteOneBit(pBuffer, bitData, nStart, nStart); 
  } 
 
  //再写Set数据 
  while ( nSet ) 
  { 
    byteData = ptData[--nSet]; 
    //写一个byte 
    int i=0; 
    while ( i!=8 ) 
    { 
      ReadOneBit(&byteData, i++, nTempEnd, bitData); 
      WriteOneBit(pBuffer, bitData, nStart, nStart); 
    } 
  } 
  nEnd = nStart; 
 
} 
 
 
void WtriteStringToBuffer( byte* pBuffer, char* pchar, int nStart, int nCount, /* out */int& nEnd ) 
{ 
  for ( int nIndex=0; nIndex<nCount; nIndex++ ) 
  { 
    WriteDataToBuffer(pBuffer, pchar[nIndex], nStart, 8, nStart); 
  } 
  nEnd = nStart; 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助。

更多精彩内容其他人还在看

C++广播通信实例

这篇文章主要介绍了C++实现广播通信的方法,实例讲述了C++ socket广播通信的原理与实现方法,需要的朋友可以参考下
收藏 0 赞 0 分享

C++计算ICMP头的校验和实例

这篇文章主要介绍了C++计算ICMP头的校验和的方法,代码简单实用,对于校验ICMP报文来说有不错的实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

C++设置超时时间的简单实现方法

这篇文章主要介绍了C++设置超时时间的简单实现方法,涉及系统函数setsockopt对套接口的操作,具有一定的实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

C++实现ping程序实例

这篇文章主要介绍了C++实现ping程序实例,涉及C++对于ICMP数据包的发送与回显处理,具有一定的实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

C++之boost::array的用法

这篇文章主要介绍了C++之boost::array的用法,以实例的形式简单讲述了静态数组的容器boost::array的使用技巧,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

C++之Boost::array用法简介

这篇文章主要介绍了C++之Boost::array用法简介,较为详细的分析了Boost::array中的常见用法,并用实例的形式予以总结归纳,需要的朋友可以参考下
收藏 0 赞 0 分享

VC文件目录常见操作实例汇总

这篇文章主要介绍了VC文件目录常见操作实例汇总,总结了VC针对文件目录的各种常用操作,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

VC打印word,excel文本文件的方法

这篇文章主要介绍了VC打印word,excel文本文件的方法,是VC操作文本文件中非常实用的技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

VC++获得当前进程运行目录的方法

这篇文章主要介绍了VC++获得当前进程运行目录的方法,可通过系统函数实现该功能,是非常实用的技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

VC中SendMessage和PostMessage的区别

这篇文章主要介绍了VC中SendMessage和PostMessage的区别,较为全面的分析了SendMessage和PostMessage运行原理及用法上的不同之处,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多