是否可以用位而不是字节来执行memcpy?
我想知道是否可以按位而不是按字节执行memcpy 我正在为带有VLAN标记的以太网帧编写一个C代码,其中我需要为VLAN头属性(PCP-3bit、DEI-1bit、VID-12bit)填充不同的值 如何对这些位执行memcpy操作,或者如何以位填充这些属性的值是否可以用位而不是字节来执行memcpy?,c,ethernet,memcpy,C,Ethernet,Memcpy,我想知道是否可以按位而不是按字节执行memcpy 我正在为带有VLAN标记的以太网帧编写一个C代码,其中我需要为VLAN头属性(PCP-3bit、DEI-1bit、VID-12bit)填充不同的值 如何对这些位执行memcpy操作,或者如何以位填充这些属性的值 提前谢谢 如果需要填充字段,可以将C与结构一起使用,如下所示: struct box_props { unsigned first : 1; unsigned second : 3; unsigned : 4;
提前谢谢 如果需要填充字段,可以将C与结构一起使用,如下所示:
struct box_props {
unsigned first : 1;
unsigned second : 3;
unsigned : 4;
};
例如,其中1
表示字段长度为1比特。最后一个(未命名)字段表示:4位填充
为它定义struct
,memcpy
,并读取字段,就像它们在未签名的地方一样。写作也一样
注意:始终填充到整数字节,或memcpy
可能会产生不必要的影响 否。位是不可寻址的(这意味着不可能直接从内存中读取它们,只能直接从内存中读取它们。它们没有地址。只有字节有地址)
您需要读取包含您感兴趣的位的字节或字,然后自己进行操作。我已经为一个客户机完成了802.1Q VLAN帧标记,该客户机只有802.3以太网帧,但希望迁移到802.1Q,因为安装了新的VLAN感知交换机
首先,不能复制位。我们使用memcpy复制了以字节为单位的标记
插图(有关字段的说明,请参阅维基百科):-
VLAN标签=4字节;由TPID(2字节)和TCI(2字节)组成
TPID很简单,始终为0x8100,表示VLAN标记的帧
TCI由PCP-3位、DEI-1位、VID-12位组成。将TCI分解为半字节,即4位。默认情况下,半字节(PCP+DEI)=0x0,假设优先级已禁用且DEI=0。剩下的3个半字节(12位)用于VLAN-ID本身。比如说,您想要为VLAN-ID=123标记一个帧。在十六进制中,这将是=0x07B
将半字节分组在一起,就有了2字节的TCI字段,现在可以看到0x007B
然后你可以做下面的事情。(代码未编译)
最重要的问题是,作为拷贝的一部分,您是否希望位相对于8位边界发生移位;您是否希望位重叠?memcpy将n字节从源复制到目标。您不能将memcpy
用于位。出于同样的原因,我需要此功能,请提供如何解决此问题的答案。请注意,这完全是实现定义的。详情请参见,但基本上是订单和包装不便于携带。谢谢。。。我将尝试使用结构化方法。但请记住其他人所说的话以及@detly链接的答案(我想我应该更新我的C-fu):这是不可移植的,可能会出现奇怪的bug。实际上,Pascal给了你一个规范的答案。这是PCP和DEI为0的简单部分,现在让我们假设vlanID为4011,PCP7与DEI为0,我希望看到这一点(因为我真的很难做到!)正如我所说,您需要将TCI字段想象为16位或4位字节。第一个半字节是PCP+DEI=7,其余3个半字节是VLAN-ID=4011。将二进制位转换为十六进制后,TCI字段将为0xEFAB。
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));