2013-06-26 35 views
5

我想知道是否可以按位而不是来执行memcpy?是否可以在位而不是字节中执行memcpy?

我正在写一个带有VLAN标记的以太网帧的C代码,其中我需要为VLAN标头属性(PCP-3bits,DEI-1bit,VID-12bits)填充不同的值。

如何对这些位执行memcpy,或者以任何其他可能性向位中的这些属性填充值。

在此先感谢!

+0

最重要的问题是您是否期望位作为副本的一部分相对于8位边界进行移位;你认为这些位可能会重叠吗? –

+1

memcpy从源到目的地拷贝n'字节'。你不能使用'memcpy'作为位。 –

+0

我需要此功能出于同样的原因,请提供有关如何解决此问题的答案。 – jwbensley

回答

1

如果您需要填写的字段,你可以使用C bit-fieldsstruct,像这样:

struct box_props { 
    unsigned first : 1; 
    unsigned second : 3; 
    unsigned : 4; 
}; 

1,例如,表示该字段是1位长。最后一个(未命名)字段表示:4位填充。

定义struct, memcpy它并阅读领域,就好像他们在哪里unsigned。写作相同。

注意:总是填充到整数字节,或者memcpy可能会产生不必要的影响。

+1

请注意,这完全是实现定义的。有关详细信息,请参见[本答案](http://stackoverflow.com/a/1490669/188535),但基本上它是不可移植的订单和包装。 – detly

+0

谢谢......我会尝试使用结构方法。 – arr

+0

但请记住其他人所说的以及由@detly链接的SO答案(我想我应该更新我的C-fu):这不是可移植的,可能会出现奇怪的错误。其实,帕斯卡给你提供了规范的答案。 –

6

编号位不可寻址(意味着它不可能直接从内存中读取它们,它们没有地址,只有字节有地址)。

您需要读取包含您感兴趣的位的字节或单词,并自己执行masking

1

我已经为客户端完成802.1Q VLAN标记,他们只有802.3以太网帧,但希望迁移到802.1Q,因为安装了新的VLAN感知交换机。

首先,你不能复制位。我们使用memcpy以字节复制标签。

插图(参照维基百科字段的说明): -

VLAN标记= 4字节;由TPID(2字节)和TCI(2字节)组成。

TPID很简单,始终为0x8100,指示带VLAN标记的帧。

TCI由PCP-3bits,DEI-1bit,VID-12bits组成。将TCI细分为四位,即四位。缺省情况下,半字节(PCP + DEI)= 0x0,假设优先级被禁用且DEI = 0。其余3个半字节(12位)用于VLAN-ID本身。假设你想标记一个VLAN-ID = 123的帧。在十六进制中这将是= 0x07B。

将小数点组合在一起,在那里您可以看到2字节的TCI字段,现在可以将其视为0x007B。

然后您可以执行以下操作。 (代码未编译)

unsigned short int vlanTPID, vlanTCI; 
unsigned char  *dest, *src; 

// Set the VLAN Tag 
vlanTPID = 0x8100; 
vlanTCI = 0x007B; 

// Pointer to the TPID position of ethernet frame 
dest = &vlanTagPosition; 
src = &vlanTPID; 
memcpy(dest, src, sizeof(vlanTPID)); 

// Increment dest pointer by 2 bytes to insert TCI in the ethernet frame 
dest += 2; 
src = &vlanTCI; 
memcpy(dest, src, sizeof(vlanTCI)); 
+0

这是PCP和DEI都为0的简单部分,现在让我们假设一个vlanID为4011和一个DEI为0的PCP 7,我希望看到这一点(因为我真的为此付出了努力!)。 – jwbensley

+0

| 1 1 1 0 | 1 1 1 1 | 1 0 1 0 | 1 0 1 1 | - 正如我所说的,您需要将TCI字段想象成16位或4位半字节。第一个半字节是PCP + DEI = 7,其余3个半字节是VLAN-ID = 4011.一旦将二进制位转换为十六进制,您的TCI字段将为0xEFAB。 – ritwick87

相关问题