26

Is the following program a strictly conforming program in C? I am interested in c90 and c99 but c11 answers are also acceptable.

#include <stdio.h>
#include <string.h>

struct S { int array[2]; };

int main () {
    struct S a = { { 1, 2 } };
    struct S b;
    b = a;
    if (memcmp(b.array, a.array, sizeof(b.array)) == 0) {
        puts("ok");
    }
    return 0;
}

In comments to my answer in a different question, Eric Postpischil insists that the program output will change depending on the platform, primarily due to the possibility of uninitialized padding bits. I thought the struct assignment would overwrite all bits in b to be the same as in a. But, C99 does not seem to offer such a guarantee. From Section 6.5.16.1 p2:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

What is meant by "converted" and "replaces" in the context of compound types?

Finally, consider the same program, except that the definitions of a and b are made global. Would that program be a strictly conforming program?

Edit: Just wanted to summarize some of the discussion material here, and not add my own answer, since I don't really have one of my own creation.

  • The program is not strictly conforming. Since the assignment is by value and not by representation, b.array may or may not contain bits set differently from a.array.
  • a doesn't need to be converted since it is the same type as b, but the replacement is by value, and done member by member.
  • Even if the definitions in a and b are made global, post assignment, b.array may or may not contain bits set differently from a.array. (There was little discussion about the padding bytes in b, but the posted question was not about structure comparison. c99 lacks a mention of how padding is initialized in static storage, but c11 explicitly states it is zero initialized.)
  • On a side note, there is agreement that the memcmp is well defined if b was initialized with memcpy from a.

My thanks to all involved in the discussion.

4

2 に答える 2

4

C99 §6.2.6 で

§6.2.6.1 一般

1 この節で述べられている場合を除き、すべてのタイプの表現は規定されていません。

[...]

4 [..] 同じオブジェクト表現を持つ 2 つの値 (NaN 以外) は等しいと比較されますが、等しいと比較される値は異なるオブジェクト表現を持つ場合があります。

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

42) したがって、たとえば、構造割り当てではパディング ビットをコピーする必要はありません。

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

§6.2.6.2 整数型

[...]

2 符号付き整数型の場合、オブジェクト表現のビットは、値ビット、パディング ビット、および符号ビットの 3 つのグループに分けられます。パディング ビットは必要ありません。[...]

[...]

5 パディング ビットの値は指定されていません。[...]

J.1 未規定の振る舞い

  • 構造体または共用体に値を格納するときのパディング バイトの値 (6.2.6.1)。

[...]

  • 整数表現のパディング ビットの値 (6.2.6.2)。

したがって、aとの表現にはb、値には影響しないが異なるビットが存在する場合があります。これは他の回答と同じ結論ですが、標準からのこれらの引用は良い追加のコンテキストになると思いました。


a を実行するとmemcpymemcmp常に 0 が返され、プログラムは厳密に準拠しています。はmemcpy、 のオブジェクト表現を に複製しaますb

于 2012-08-16T21:13:21.480 に答える
0

私の意見では、それは厳密に準拠しています。EricPostpischilが言及した4.5によると:

厳密に準拠するプログラムは、この国際規格で指定されている言語とライブラリの機能のみを使用するものとします。未指定、未定義、または実装定義の動作に依存する出力を生成してはならず、実装の最小制限を超えてはなりません。

問題の動作はの動作でありmemcmp、これは明確に定義されており、未指定、未定義、または実装定義の側面はありません。値、パディングビット、トラップ表現について何も知らなくても、表現の生のビットで機能します。したがって、この特定の場合の結果機能ではない)はmemcmp、これらのバイト内に格納されている値の実装に依存します。

6.2.6.2の脚注43):

同じ有効タイプTのオブジェクトxとyは、タイプTのオブジェクトとしてアクセスされたときに同じ値を持つ可能性がありますが、他のコンテキストでは異なる値を持つ可能性があります。特に、タイプTに対して==が定義されている場合、x == yはmemcmp(&x、&y、sizeof(T))== 0を意味しません。さらに、x==yは必ずしもxとyを意味しません。同じ値を持ちます。タイプTの値に対する他の操作は、それらを区別する場合があります。

編集:

もう少し考えてみると、これが原因で、厳密に準拠していることについてはよくわかりません。

指定されていないものに依存する出力を生成してはならない[...]

明らかに、の結果はmemcmp表現の不特定の動作に依存し、それによって、それmemcmp自体の動作が明確に定義されている場合でも、この節を満たします。この句は、出力が発生するまで機能の深さについては何も述べていません。

したがって、厳密には準拠していません。

編集2:

memcpy構造体をコピーするために使用されたときに厳密に準拠するようになるかどうかはわかりません。付録Jによると、a初期化されると不特定の動作が発生します。

struct S a = { { 1, 2 } };

memcpyパディングビットは変更されず、常に0を返すと仮定しても、パディングビットを使用して結果を取得します。そして、それはそれらが変わらないという仮定に依存していますが、これについての基準には保証がありません。

アラインメントに使用される構造体のパディングバイトと、などの特定のネイティブタイプのパディングビットを区別する必要がありますint。パディングバイトは変更されないと安全に想定できますが、実際の理由がないという理由だけで、パディングビットには同じことが当てはまりません。この規格では、パディングビットの例としてパリ​​ティフラグについて言及しています。これは、実装のソフトウェア機能である可能性がありますが、ハードウェア機能である可能性もあります。したがって、何らかの理由で読み取りアクセスで変更されるものを含め、パディングビットに使用される他のハードウェアフラグが存在する可能性があります。

そのようなエキゾチックなマシンと実装を見つけるのは難しいでしょうが、これを禁止するものは何もありません。私が間違っている場合は私を訂正してください。

于 2012-08-16T21:23:06.567 に答える