memcpy をバイト単位ではなくビット単位で行うことは可能ですか?
VLAN タグ付けを使用してイーサネット フレームの C コードを作成しています。このコードでは、VLAN ヘッダー属性 (PCP-3bits、DEI-1bit、VID-12bits) に異なる値を入力する必要があります。
これらのビットにmemcpyを実行するにはどうすればよいですか、またはこれらの属性にビット単位で値を入力するその他の可能性はありますか。
前もって感謝します !
いいえ。ビットはアドレス可能ではありません (つまり、ビットのみをメモリから直接読み取ることはできません。ビットにはアドレスがありません。バイトのみにアドレスがあります)。
関心のあるビットを含むバイトまたはワードを読み取り、自分でマスキングを行う必要があります。
802.3 イーサネット フレームしかないクライアントのフレームに 802.1Q VLAN タグ付けを行いましたが、新しい VLAN 対応スイッチがインストールされていたため、802.1Q に移行したいと考えていました。
まず、ビットをコピーすることはできません。memcpy を使用してタグをバイト単位でコピーしました。
イラスト (フィールドの説明についてはウィキペディアを参照してください):-
VLAN タグ = 4 バイト。TPID(2バイト)とTCI(2バイト)で構成されます。
TPID は単純で、VLAN タグ付きフレームを示す常に 0x8100 です。
TCI は、PCP-3 ビット、DEI-1 ビット、VID-12 ビットで構成されます。TCI をニブル、つまり 4 ビットに分割します。デフォルトでは、ニブル (PCP+DEI) = 0x0 で、優先度が無効であり、DEI = 0 であると仮定します。残りの 3 ニブル (12 ビット) は、VLAN-ID 自体用です。たとえば、VLAN-ID = 123 のフレームにタグを付けたいとします。16 進数では、これは = 0x07B になります。
ニブルをグループ化すると、0x007B として表示される 2 バイトの TCI フィールドができます。
次に、以下を実行できます。(コードはコンパイルされません)
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));
フィールドに入力する必要がある場合は、次のように Cビットフィールドを で使用できますstruct
。
struct box_props {
unsigned first : 1;
unsigned second : 3;
unsigned : 4;
};
たとえば1
、 は、フィールドの長さが 1 ビットであることを意味します。最後の (名前のない) フィールドは、4 ビットのパディングを意味します。
を定義しstruct
、memcpy
フィールドをあたかもどこにあるかのように読み取りますunsigned
。書き込みも同じ。
注:常に整数バイトにパディングしてください。そうしないと、memcpy
望ましくない影響が生じる可能性があります。