从c ++中的位数组/位图读取字段

时间:2013-10-29 04:24:41

标签: c++ bit-manipulation bit

背景

我有兴趣使用定义一组字段的位数组/位图。具体来说,我想解析radiotap标题,但我遇到了一些概念上的问题(或者,更可能的是,我只是错过了一些关于这一切是如何工作的)。

位数组描述的字段radiotap标头在上面的链接中定义。

问题:(已编辑)

例如,当我的数据是u_char流时,我将如何读取位图和字段中的值?我如何访问一个特定的字段,因为我知道它的存在是由位图指示的?

我认为这里的解决方案与位移/屏蔽有关,但这是我第一次尝试低级别编程,我不知道如何开始解决这个问题。

修改

目前我的问题是我正在从u_char指针读取802.11帧,但是我一直在以编程方式从这里开始访问我所知道的标题和字段,首先是radiotap标题。

//defined by library I'm using
struct packet_header {

    struct timeval ts; /*timestamp*/
    bpf_u_int32 caplen; /*number of stored bytes*/
    bpf_u_int32 length; /*total length of packet*/

}

struct packet_header hdr; //see above, basic info
u_char *packet //the data

for(int i = 0; i <  hdr->length; i++){

    //parse/analyse data contained in the frame/packet (1st radiotap)
    packet[i] //do something with u_char here, but what exactly?


}

2 个答案:

答案 0 :(得分:2)

我建议你仔细研究这个页面:http://www.radiotap.org/Radiotap

标题的it_present字段表示标题后面的字段。并且存在的字段按其位数顺序排列,从最低到最高。因此,例如,如果it_present中的第一个非零位是第3位,则标头后面的第一个字段将是通道。

这个协议非常复杂,必须遵循许多规则。例如,如果设置了it_present的第31位,则不是紧跟在标题之后的字段,而是首先存在更多的存在位。您还必须了解字段的对齐方式。字段之间可能存在填充,因此32位字段在4字节边界上对齐,64位字段在8字节边界上对齐,依此类推。

编辑:我们假设packet指向radiotap标头的开头,pkt_len是字节数。你可以像这样开始:

pkt_len = hdr.length;
if ( pkt_len >= sizeof(ieee80211_radiotap_header) )
{
  u_int16_t  it_len;
  u_int32_t  it_present;
  u_int32_t  tmpMask;
  u_int32_t* pExtraMask;
  u_int32_t* pNextMask;
  u_int32_t  uMask;
  int        iFldNum;

  ieee80211_radiotap_header* pPktHdr = (ieee80211_radiotap_header*) packet;
  pkt_len -= sizeof(ieee80211_radiotap_header);
  packet += sizeof(ieee80211_radiotap_header);
  it_len = le16_to_cpu(pPktHdr->it_len);          // Get radiotap packet length from header
  it_present = le32_to_cpu(pPktHdr->it_present);  // Get present field bitmask

  // Find end of radiotap header
  tmpMask = it_present;
  pExtraMask = pNextMask = (u_int32_t*) packet;
  while ( (tmpMask & 0x80000000) && (pkt_len >= sizeof(u_int32_t)) )
  {
    tmpMask = le32_to_cpu(*pNextMask++);
    pkt_len -= sizeof(u_int32_t);
    packet += sizeof(u_int32_t);
  }
  // packet should now point to the first field
  for ( iFldNum = 0, uMask = 1; (iFldNum < 31) && pkt_len; ++iFldNum, uMask <<= 1 )
  {
    if ( (it_present & uMask) )
    {
      u_int16_t uFldLen;

      // We have a non-zero bit in the mask, iFldNum is the field number
      // Call function to extract the field at packet and return number of bytes used
      // process_field() is responsible for data alignment and preventing buffer overrun
      uFldLen = process_field(packet, pkt_len, iFldNum);
      pkt_len -= uFldLen;
      packet += uFldLen;
    }
  }
  // Here you would check if it_present had bit 31 set
  // If so, process additional masks starting at pExtraMask
}

正如你所看到的,它可能会有点毛茸茸。

答案 1 :(得分:0)

我不确定我的问题是否正确。我假设你在询问如何在第3位读取一些值。

因此,您可以正常读取值并将其左移3个位置。

x = 1; x = x&lt;&lt; 3;