memcmpで構造体を比較しないでください

1108 ワード

2つの構造体を比較する場合、構造体に大量のメンバー変数が含まれている場合、プログラマは便利のためにmemcmpを直接使用して2つの構造体を比較し、各メンバーを別々に比較することを避けることが多い.このようなコードは簡単に書けますが、隠れた危険を隠す可能性が高いです.次のサンプルコードを参照してください.
#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を直接使用して構造体を比較しないでください.