2016-11-24 12 views
0

最近、いくつかの論文とコードをcrc計算で読みました(例えば、A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMSthe implementation in Linux)。私が理解する限り、crcは特定のアドレスからバイトごとに開始されます。 Linuxカーネルから構造体のcrc16を計算する方法

例:

u16 crc16(u16 crc, u8 const *buffer, size_t len) 
{ 
    while (len--) 
    crc = crc16_byte(crc, *buffer++); 
    return crc; 
} 

は、今私は自分自身を求めていますが、それは可能であるstructで簡単にこれを行うには?

+1

ポインタを構造体にキャストできます: 'struct whatever x; –

+1

CRCを同じクロスコンパイラ(少なくとも)に頼っているのであれば(例えばstruct padding)、 –

+0

@ JohnnyMoppが答えを出しましたが、そこには欠陥があります。構造体にはコンパイラによって挿入されたパディングが含まれている可能性があります。パディングの値は不確定ですが、チェックサムの計算に使用されます。明示的に初期化する前に 'memset'を使って構造全体をゼロに設定することが推奨されます。それ以外の場合は、同じ構造の2つのチェックサムが異なることがあります。 –

答えて

4

賢明な結果を望むのであれば、一般的ではありません。

これは、CRCが一連の「既知」バイトにわたって計算され、メモリ内の構造がではなく、の既知のバイトシーケンスであるためです。異なるシステム/プラットフォーム上でさまざまなフィールドをさまざまなサイズにすることができます(struct自体がそうであるように)。

最初に構造体を既知の安定したマッピングを持つバイト列にシリアル化することができれば、もちろんそのシーケンスにCRCを適用できます。これは、buffer引数がconst u8 *であること、すなわち、定数バイトへのポインタであり、const void *ではないことが(微妙に)示唆されている。あなたが気にしない、と(例えば)あなたはコンパイラの設定を変更および/または別のシステムにプログラムを移動した場合破壊気にしない場合は

、あなただけ使用できます。

const struct mystruct s = { ... }; 
const u16 crc = crc16(0, (u8 *) &s, sizeof s); 

しかし、このにはに構造体のパディングが含まれるため、非常に危険です。

+0

構造体を梱包することは、この状況で少し役に立ちます。 – j123b567

+0

@ j123b567:梱包は標準ではなく、何も保証しません。それは無視することができるだけでなく、エンディアンやビットフィールドなども定義しません。また、多くのアーキテクチャでは、パッキングはアクセスを遅くするか、sizeof> 1の型の手動アセンブリを必要とします。 – Olaf

+0

@Olafあなたはもちろん正しいです。しかし、あなたは常にコードを書いています、それはあらゆるコンパイラによってコンパイルされ、どのプロセッサでも実行する必要がありますか?環境が分かっていれば、構造体のパッキングが役立ちます。この状況を処理するのは簡単なトリックです。 (例えば、マイクロコントローラ上のCRCを用いたEEPROMへのコンフィギュレーション構造の書込み) – j123b567

関連する問題