11

同一のメンバーを持つように初期化された 2 つの C 構造体がある場合、次のことを保証できますか?

memcmp(&struct1, &struct2, sizeof(my_struct))

は常にゼロを返しますか?

4

5 に答える 5

10

memcmp同等性をテストするための構造を安全に構築できるとは思いません。

C11 §6.2.6.6 型の表現から

値が構造体型または共用体型のオブジェクト (メンバー オブジェクトを含む) に格納される場合、パディング バイトに対応するオブジェクト表現のバイトは指定されていない値を取ります。

これは、構造の個々の要素を比較する関数を書く必要があることを意味します

int my_struct_equals(my_struct* s1, my_struct* s2)
{
    if (s1->intval == s2->intval &&
        strcmp(s1->strval, s2->strval) == 0 && 
        s1->binlen == s2->binlen &&
        memcmp(s1->binval, s2->binval, s1->binlen) == 0 &&
        ...
        ) {
        return 1;
    }
    return 0;
}
于 2013-05-29T13:48:15.583 に答える
9

いいえ、すべてのメンバーが等しい 2 つの構造体は、 paddingmemcmp()のために、に対して等しくない場合があります。

もっともらしい例は次のとおりです。の初期化のためst2に、標準準拠の 32 ビット コンパイラは、初期化されていない最後のパディングの一部を残す一連のアセンブリ命令を生成できます。このパディングには、たまたまスタック上にあったものがすべて含まれますが、st1のパディングには通常ゼロが含まれます。

struct S { short s1; long long i; short s2; } st1 = { 1, 2, 3 };
int main() {
  struct S st2 = { 1, 2, 3 };
  ... at this point memcmp(&st1, &st2, sizeof(struct S)) could plausibly be nonzero
}
于 2013-05-29T13:47:44.230 に答える
2

両方の変数がグローバルまたは静的であり、それらのメンバーがプログラムの初期化時に初期化されている場合、はい、それらは と等しいと比較されmemcmp()ます。(注: ほとんどのシステムは、データ ページをゼロの初期化ページにロードするだけですが、C 標準はこの動作を保証しません。)

また、構造体の 1 つが を使用して他の構造体で初期化された場合memcpy()、それらは と等しくなりmemcmp()ます。

メンバーが同じ値に初期化される前に、両方が最初に何らかの共通の値にmemset()初期化された場合、それらは同等と比較memcmp()されます (メンバーも構造体でない限り、同じ制限が再帰的に適用されます)。

于 2013-05-29T13:54:08.840 に答える
2

構造体パディングの明白なケースのほかに、単一の変数に対してさえ保証されていません。6.2.6.1 (8) の脚注を参照してください。

同じ実効型 を持つオブジェクトxとは、 type のオブジェクトとしてアクセスされたときに同じ値を持つことができますが 、他のコンテキストでは異なる値を持つことができます。特に、 type に対して が定義されている場合、 はそれを意味しません 。さらに、必ずしもそれを意味するわけではなく、同じ値を持っています。タイプの値に対する他の操作は、それらを区別する場合があります。yTT==Tx == ymemcmp(&x, &y, sizeof (T)) == 0x == yxyT

于 2013-05-30T10:07:36.027 に答える
-1

たとえば、次のように、両方のメモリブロックが読み込まれる前に初期化されていることを確認すると、それらが同一であることを保証できますmemset

memset(&struct1, 0, sizeof(my_struct))

コメントストリームが便利なので、ここに残して編集します。

于 2013-05-29T14:11:41.353 に答える