我想知道是否可以按比特而不是字节 memcpy ?
我正在为带有VLAN标记的以太网帧编写C代码,我需要填写VLAN标头属性的不同值(PCP-3bits,DEI-1bit,VID-12bits)。
如何对这些位执行memcpy,或者以位为单位填充这些属性的任何其他可能性。
提前致谢!
答案 0 :(得分:7)
没有。位不可寻址(意味着不能直接从内存中读取它们。它们没有地址。只有字节有地址)。
您需要读取包含您感兴趣的位的字节或单词,并自己执行masking。
答案 1 :(得分:1)
如果您需要填写字段,可以将C bit-fields与struct
一起使用,如下所示:
struct box_props {
unsigned first : 1;
unsigned second : 3;
unsigned : 4;
};
例如,1
表示该字段长度为1位。最后一个(未命名的)字段表示:4位填充。
为其定义struct
,memcpy
并将字段读取为unsigned
。写作也一样。
注意:始终填充整数字节,或memcpy
可能会产生不良影响。
答案 2 :(得分:1)
我已经为客户端完成了帧的802.1Q VLAN标记,他们只有802.3以太网帧,但由于安装了新的VLAN感知交换机,因此希望迁移到802.1Q。
首先,你不能复制比特。我们使用memcpy以字节为单位复制了标记。
插图(有关字段的说明,请参阅维基百科): -
VLAN标记= 4字节;由TPID(2字节)和TCI(2字节)组成。
TPID很简单,始终为0x8100,表示VLAN标记帧。
TCI由PCP-3bits,DEI-1bit,VID-12bits组成。将TCI分解为半字节,即4位。默认情况下,半字节(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));