是可以用比特而不是字节来做memcpy吗?

时间:2013-06-26 12:55:30

标签: c ethernet memcpy

我想知道是否可以按比特而不是字节 memcpy

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

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

提前致谢!

3 个答案:

答案 0 :(得分:7)

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

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

答案 1 :(得分:1)

如果您需要填写字段,可以将C bit-fieldsstruct一起使用,如下所示:

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

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

为其定义structmemcpy并将字段读取为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));