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

在我创业的一个项目中,为了节约网络带宽,因此在网络中传输数据需要实现紧凑存取,在国防,科研,航天,军工等多个领域其实也有类似的需求。
实现紧凑存取,不是按一个字节一个字节地存取,而是按位存取。比如一个字节,我们可以存储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语言实现、c语言接口与实现 pdf、des加密算法c语言实现、算法 c语言实现,以便于您获取更多的相关知识。

时间: 2024-10-31 15:57:24

如何在C++中实现按位存取_C 语言的相关文章

如何在C++中建立一个顺序表_C 语言

准备数据 复制代码 代码如下: #define MAXLEN 100 //定义顺序表的最大长度struct DATA{ char key[10]; //结点的关键字  char name[20]; int age;};struct SLType //定义顺序表结构 { DATA ListData[MAXLEN+1];//保存顺序表的结构数组 int ListLen;   //顺序表已存结点的数量 }; 定义了顺序表的最大长度MAXLEN.顺序表数据元素的类型DATA以及顺序表的数据结构SLTyp

如何在UpdatePanel中调用JS客户端脚本_C#教程

页面中加入了UpdatePanel后,Response.Write("<script>function dis (){alert('这是调用写在server的JS');}</script>")来调用客户端脚本,无任何提示的无反应.如何在UpdatePanel中调用JS客户端脚本呢? 方法:采用 ScriptManager.RegisterStartupScript(Control controlId,Type this.GetType(),String key,

如何在win8中更改键盘输入或键盘语言

您可以按照以下步骤更改键盘输入设置: 1. 从开始屏幕,打开"控制面板". 2. 单击"常规",然后在右窗格中单击"添加输入语言". 3. 在语言列表中,单击您想要选择的语言旁边的"选项".(如果列表中没有您想要的语言,请单击"添加语言",选择想要的语言,然后单击"添加到列表".) 4. 在这些语言选项中,单击"添加输入法". 5. 从选项列表中选择键盘布局,单击&q

如何在Windows8中找出消失不见的语言栏

  1.系统下同时按住键盘上 "Windows" 和 "X" 键打开系统菜单 ,选择"控制面板"; 2.通过大图标找到"通知区域图标";如下图所示: 3.点击"启用或关闭系统图标";如下图所示: 4.找到"输入指示",从下拉框选中"启用",再点"确认"即可.如下图所示: 5.输入法图标又回到了任务栏.如下图所示:

浅谈Windows系统下C语言编程中Glib库的使用_C 语言

在这个C的变成世界里,有许多实用的库,其中最有名的且最通用(跨多个平台的实现包括Windows,要知道很多实用的编程库都不提供Windows的实现)就是GLib这个库,其中就有实现线程的部分. glib库是Linux平台下最常用的C语言函数库,它具有很好的可移植性和实用性. glib是Gtk +库和Gnome的基础.glib可以在多个平台下使用,比如Linux.Unix.Windows等.glib为许多标准的.常用的C语言结构提供了相应的替代物. 如果在程序中要使用到glib库中的函数,则应该包

C语言左旋转字符串与翻转字符串中单词顺序的方法_C 语言

左旋转字符串题目: 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部. 如把字符串 abcdef  左旋转 2  位得到字符串 cdefab.请实现字符串左旋转的函数. 要求时间对长度为 n  的字符串操作的复杂度为 O(n),辅助内存为 O(1). 分析: 网上看到解法很多种,就不详细说明了. 我采用的是数组不对称的交换时间复杂度应该是O(n). 代码实现(GCC编译通过): #include "stdio.h" #include "stdlib.h&qu

探讨C语言中关键字volatile的含义_C 语言

volatile 的意思是"易失的,易改变的".这个限定词的含义是向编译器指明变量的内容可能会由于其他程序的修改而变化.通常在程序中申明了一个变量时,编译器会尽量把它存放在通用寄存器中,例如ebx.当CPU把其值放到ebx中后就不会再关心对应内存中的值.若此时其他程序(例如内核程序或一个中断)修改了内存中它的值,ebx中的值并不会随之更新.为了解决这种情况就创建了volatile限定词,让代码在引用该变量时一定要从指定位置取得其值. 关键字volatile有什么含意?并给出三个不同的例

深入理解结构体中占位符的用法_C 语言

复制代码 代码如下: typedef union{    struct x{    char a1 : 2;    char b1 : 3;    char c1 : 3;    }x1;    char c;}my_un;int main(){    my_un a;    a.c = 100;    printf("%d/n",a.x1.c1);    printf("%d/n",sizeof(my_un));     return 0;} 输出结果:31即第一

C++中string的模拟实现_C 语言

c++中的string类可以实现字符串对象的一系列操作,如下图就是从cplusplus上截取的string的一部分功能: 接下来我就简单模拟几个函数实现  首先,我们要给出完整的string类,包括构造函数,析构函数,私有成员char* str  并且在类内声明要实现的函数(本文我只实现了operator=,operator[ ],pushback(),以及三个operator+=,五个insert等)  #include<iostream> #include<cstring> u