memcmpで構造体を比較しないでください
1108 ワード
2つの構造体を比較する場合、構造体に大量のメンバー変数が含まれている場合、プログラマは便利のためにmemcmpを直接使用して2つの構造体を比較し、各メンバーを別々に比較することを避けることが多い.このようなコードは簡単に書けますが、隠れた危険を隠す可能性が高いです.次のサンプルコードを参照してください.
最終結果:#./a.out No equal!
どうしてこんな結果になったの?経験のある読者はすぐに反応します.これは位置合わせによるものです.
間違いない!struct padding_type->m 1のタイプはshortタイプであり、m 2のタイプはintタイプである.自然整列規則に従ってstruct padding_typeは4バイトの位置合わせが必要です.したがって、コンパイラはm 1の後ろに2つのpaddingバイトを挿入しますが、この2つのバイトの内容は「ランダム」です.構造体bはmemsetを呼び出して構造体全体に消費されるメモリをクリアしたため、paddingの値は自然に0となる.このようにmemcmpを用いて2つの構造体を比較すると,結論は異なり,すなわち戻り値は0ではない.
したがって、プロジェクト内ですべての構造体がmemsetを使用して初期化されることを保証できない限り(これは保証しにくい)、memcmpを直接使用して構造体を比較しないでください.
#include
#include
#include
typedef struct padding_type {
short m1;
int m2;
}padding_type_t;
int main()
{
padding_type_t a = {
.m1 = 0,
.m2 = 0,
};
padding_type_t b;
memset(&b, 0, sizeof(b));
if (0 == memcmp(&a, &b, sizeof(a))) {
printf("Equal!
");
}else {
printf("No equal!
");
}
return 0;
}
最終結果:#./a.out No equal!
どうしてこんな結果になったの?経験のある読者はすぐに反応します.これは位置合わせによるものです.
間違いない!struct padding_type->m 1のタイプはshortタイプであり、m 2のタイプはintタイプである.自然整列規則に従ってstruct padding_typeは4バイトの位置合わせが必要です.したがって、コンパイラはm 1の後ろに2つのpaddingバイトを挿入しますが、この2つのバイトの内容は「ランダム」です.構造体bはmemsetを呼び出して構造体全体に消費されるメモリをクリアしたため、paddingの値は自然に0となる.このようにmemcmpを用いて2つの構造体を比較すると,結論は異なり,すなわち戻り値は0ではない.
したがって、プロジェクト内ですべての構造体がmemsetを使用して初期化されることを保証できない限り(これは保証しにくい)、memcmpを直接使用して構造体を比較しないでください.