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



背景:

我对使用定义一组字段的位数组/位图感兴趣。具体来说,我想解析 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?

}

我建议你非常仔细地研究这个页面: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
}

如您所见,它可能会变得有点毛茸茸的。

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

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

x = 1 ;x = x <<3 ;

最新更新