14

たとえば、このコードは有効ですか、それともエイリアシング ルールに違反して未定義の動作を引き起こしますか?

int x;
struct s { int i; } y;
x = 1;
y = *(struct s *)&x;
printf("%d\n", y.i);

私の関心は、これに基づく手法を使用して、エイリアス読み取りを実行するための移植可能な方法を開発することです。

更新: これは意図した使用例です。少し異なりますが、上記が有効な場合にのみ有効です。

static inline uint32_t read32(const unsigned char *p)
{
    struct a { char r[4]; };
    union b { struct a r; uint32_t x; } tmp;
    tmp.r = *(struct a *)p;
    return tmp.x;
}

必要に応じて、GCC はこれを単一の 32 ビット ロードにコンパイルし、p実際に 以外の型を指している場合に発生する可能性のあるエイリアシングの問題を回避しているようですchar。つまり、GNU C__attribute__((__may_alias__))属性のポータブルな代替品として機能しているようです。しかし、それが本当に明確に定義されているかどうかはわかりません...

4

5 に答える 5

3

この文が存在するエイリアシングルール(C99、6.5p7)の私の読書:

「そのメンバーの中に前述の型の 1 つを含む集約型または共用体型 (再帰的に、部分集約型または含まれる共用体のメンバーを含む)、または」

Cのエイリアシング規則に違反していないと思います。

しかし、エイリアシング ルールに違反していないという事実だけでは、このコード スニペットが有効であるとは言えません。他の理由で未定義の動作を引き起こす可能性があります。

(struct s *) &x

struct s有効なオブジェクトを指しているとは限りません。xのアラインメントが type のオブジェクトに適していると仮定してもstruct、キャスト後の結果のポインターは、構造体オブジェクトを保持するのに十分な大きさのスペースを指していない場合があります (構造体 s は最後のメンバーの後にパディングがある可能性があるため)。

編集:答えは最初のバージョンから完全に作り直されました

于 2013-06-30T00:10:42.717 に答える
0

それが適切な答えかどうかはわかりませんが、(2番目の例で)何が起こるかは次のとおりです。

  1. コンパイラーはstruct a、配列内の 4 バイトの後にパディングがある 8 バイトのオブジェクトとして定義します (なぜですか? それは可能だからです)。
  2. 次に、p を a (つまり、8 バイト オブジェクト)tmp.r = *(struct a *)p;のアドレスとして扱う which を使用します。struct aこのオブジェクトの内容を、保持tmp.rしているアドレスから 8 バイトにコピーしようとしますp。ただし、そこから 4 バイトしか読み取れません。

実装はパディング バイトをコピーする必要はありませんが、コピーすることは許可されています。

于 2013-06-29T22:04:21.747 に答える
-1

C標準から:

オブジェクトまたは不完全な型へのポインターは、別のオブジェクトまたは不完全な型へのポインターに変換される場合があります。結果のポインターが、ポイント先の型に対して正しくアラインされていない場合 (57)、動作は未定義です。

この場合の結果のポインターは、正しく配置されること保証されているため (構造体の最初のメンバーが構造体と一致している必要があるため)、この制限はここでは適用されません。適用されるのは、オブジェクトへのアクセスがオブジェクトの「実効型」と互換性のあるポインターを介してのみ行われることを要求するポインターの使用に関する追加の制限です...この場合、の実効型はxであるintため、構造体を介してアクセスすることはできませんポインター。

一部の主張に反して、ポインター型間の変換はラウンドトリップの使用に限定されないことに注意してください。標準では、ポインターは変換可能であると規定されていますが、そのような変換が未定義の動作をもたらす場合についての条件があります。他の場所では、結果の型のポインターの使用のセマンティクスを提供します。標準の往復保証追加の仕様です...明示的に述べられていない場合は信頼できないものです。

それ以外の場合、再度変換すると、結果は元のポインターと等しくなります。

これは、往復に関する保証を指定するものであり、往復を制限するものではありません。

ただし、前述のように、「有効な型」言語、変換の結果として生じるポインタの使用に対する制限です。

于 2013-06-29T21:59:01.360 に答える