のように、他の側にそれらをデシリアライズする必要があり、あなたの代わりにシリアル化する必要があります構造体のコメントをバイトバッファとの間で(書き込み時に)、非直列化(読み込み時に)します。
これを行うにはいくつかの方法があります。たとえば、インライン関数(C99 static inline
)、プリプロセッサマクロ、各フィールドごとの個別関数、フィールドをビットパック化する汎用関数などがあります。
最も一般的なオプションは、内部構造体からバイト配列をパックしてアンパックすることです。たとえば、内部で使用されている構造体については、
struct mbxh {
INT8U channel:4;
INT8U priority:4;
INT16U length;
INT16U address;
INT8U array[4];
};
static void pack_mbxh(unsigned char *const dst, const struct mbxh *src)
{
dst[0] = src->channel | ((src->priority) << 4);
dst[1] = src->length >> 8;
dst[2] = src->length;
dst[3] = src->address >> 8;
dst[4] = src->address;
dst[5] = src->array[0];
dst[6] = src->array[1];
dst[7] = src->array[2];
dst[8] = src->array[3];
}
static void unpack_mbxh(struct mbxh *dst, const unsigned char *const src)
{
dst->channel = src[0] & 15U;
dst->priority = (src[0] >> 4) & 15U;
dst->length = (src[1] << 8) | src[2];
dst->address = (src[3] << 8) | src[4];
dst->array[0] = src[5];
dst->array[1] = src[6];
dst->array[2] = src[7];
dst->array[3] = src[8];
}
これは、バイトオーダーを指定するのが簡単なので特に便利です。上記は、length
とaddress
フィールドのビッグエンディアンまたはネットワークバイトオーダーを使用しています。
ターゲットシステムにRAMが非常に制限されている場合、プリプロセッサマクロを使用して「パック」フィールドに直接アクセスすることは、しばしば適切なオプションです。これにより、メモリは少なくなりますが、CPUリソースは増えます。 (「パック」のフィールドは、あまりにも、ここではビッグエンディアンまたはネットワークバイト順を使用することに注意してください。)実際に
#define mbxh_get_channel(data) ((data)[0] & 15U)
#define mbxh_get_priority(data) ((data)[0] >> 4)
#define mbxh_get_length(data) ((((INT16U)(data)[1]) << 8) | ((INT16U)(data)[2]))
#define mbxh_get_address(data) ((((INT16U)(data)[3]) << 8) | ((INT16U)(data)[4]))
#define mbxh_get_array(data, i) ((data)[i])
#define mbxh_set_channel(data, value) \
do { \
(data)[0] = ((data)[0] & 240U) | ((INT8U)(value)) & 15U); \
} while (0)
#define mbxh_set_priority(data, value) \
do { \
(data)[0] = ((data)[0] & 15U) | (((INT8U)(value)) & 15U) << 4); \
} while (0)
#define mbxh_set_length(data, value) \
do { \
(data)[1] = ((INT16U)(value)) >> 8; \
(data)[2] = (INT8U)(value); \
} while (0)
#define mbxh_set_address(data, value) \
do { \
(data)[3] = ((INT16U)(value)) >> 8; \
(data)[4] = (INT8U)(value); \
} while (0)
#define mbxh_set_array(data, index, value) \
do { \
(data)[(index)] = (INT8U)(value); \
} while (0)
、あなたは多くのそのような構造を持っている場合は特に、これらの組み合わせが動作します。
static INT8U get4u_lo(const INT8U *const ptr)
{
return (*ptr) & 15U;
}
static INT8U get4u_hi(const INT8U *const ptr)
{
return (*ptr) >> 4;
}
static INT16U get16u(const INT8U *const ptr)
{
return (((INT16U)ptr[0]) << 8) | ptr[1];
}
static void set4u_lo(INT8U *const ptr, INT8U val)
{
*ptr &= 240U;
*ptr |= val & 15U;
}
static void set4u_hi(INT8U *const ptr, INT8U val)
{
*ptr &= 15U;
*ptr |= (val % 15U) << 4;
}
static void set16u(INT8U *const ptr, INT16U val)
{
ptr[0] = val >> 8;
ptr[1] = val;
}
次に、あなたが使って毎の構造フィールドのアクセサを書く、低ニブル、高ニブル、または16ビットのフィールド:まず、あなたは、各タイプフィールドのにアクセスするには、いくつかのコンパクトな関数を書きますヘルパー関数上記:
#define mbxh_get_channel(data) get4u_lo((INT8U *)(data)+0)
#define mbxh_get_priority(data) get4u_hi((INT8U *)(data)+0)
#define mbxh_get_length(data) get16u((INT8U *)(data)+1)
#define mbxh_get_address(data) get16u((INT8U *)(data)+3)
#define mbxh_get_array(data, i) ((data)[5+(i)])
#define mbxh_set_channel(data, v) set4u_lo((INT8U *)(data)+0, (v))
#define mbxh_set_priority(data, v) set4u_hi((INT8U *)(data)+0, (v))
#define mbxh_set_length(data, v) set16u((INT8U *)(data)+1, (v))
#define mbxh_set_address(data, v) set16u((INT8U *)(data)+3, (v))
#define mbxh_set_array(data, i, v) ((data)[5+(i)] = (v))
この回答に記載されている例のすべてのように、上記のはあまりにもデータ用のビッグエンディアンまたはネットワークバイト順を使用しています。 channel
は4つの下位ビットにあり、最初のデータバイトの上位4ビットにはpriority
です。
全体として、デスクトップアプリケーションの場合と、内部構造を使用する場合の最初のオプション(関数呼び出しごとの構造変換)をお勧めします。マイクロコントローラやその他の制約付きメモリの場合、私はこの最新のものをお勧めします。そのあなた構造のビットフィールドを使用して
(上記のコードのいずれもがテストされていません。あなたがタイプミスやバグやその他のエラーを見つけた場合は、コメントの私を知らせ、私は上記の例のコードを修正することができますしてください。)
逐語的にネットワークに書き込む計画は、最悪の場合のユースケースです。シリアライズ/デシリアライズするためのコードを書く必要があります。これにより、コンパイラが何をしているかに依存せずに各バイトを制御できるようになります。 – unwind
ビットのパディングは決して(または常に)ありません。パディングはバイトのみに関係します。ビットフィールドは、例えば、 'channel'は1バイトです。 –
@unwind - それは正しいです。私はシリアライズ/デシリアライズしたいと思います。しかし、異なるサイズと変数の10の異なる構造がある場合、それを一般的な方法で行うにはどうすればよいですか?私は代替案を考えるのを助けることができますか?これまでのすべての答えはその構造に特有のものです...しかし、一般的なものをどんな構造でも働かせることは、私が考えることができないものです(私の脳の限界)。 –