2017-10-23 11 views
2
struct __packed element { 
    char val; 
}; 

void foo(struct element arr[4], uint32_t a) { 
    uint32_t* i = (uint32_t*)arr; 
    *i = a; 
} 

int main(void) { 
    struct element arr[4] __aligned(4); 

    foo(arr, 5); 
    ... 
} 

タイトルと同じくらい、これはCの厳密なエイリアシング違反ですか? ARRの保存されたタイプは、それはあなたがelement arr[4]を読んで、そしてarrが割り当てられた方法についてのだろうかに依存struct element[4]厳密なエイリアシング違反ですか?

+4

文字タイプを使用して、他のタイプを指すことができます。 –

+0

あなたのキャストは壊れていますので、あなたはUBを持っています。 – Stargateur

+1

'__packed'はすでにC標準の外にいます –

答えて

5

はい、これは(*i = a)厳密なエイリアシング違反です。

N1570§6.5のP7:

オブジェクトのみ 次のタイプの1つを有する左辺値表現によってアクセスその格納された値でなければならない:88)

  • と互換性タイプ
  • オブジェクトの有効な型と互換性のある型の修飾バージョン
  • 型が符号付きまたは符号なし型です。前述のいずれかを含む凝集体または共用タイプは
  • 、 オブジェクトの有効なタイプ、
  • オブジェクトの 効果的なタイプの修飾バージョンに対応する符号付きまたは符号なしのタイプであるタイプに対応します メンバー(再帰的に、サブ集約または所属ユニオンのメンバーを含む)、または
  • の文字タイプのいずれかです。上記の要件の

どれも満たされない:

  • uint32_tは、効果的なタイプcharと互換性がありません。

  • charの修飾タイプは使用していません。

  • charの符号なしバージョンではありません。

  • struct elementは、uint32_tのメンバーを持たない。

  • uint32_tは文字タイプではありません。

元の配列の有効なタイプはuint32_tであろうか、有効なタイプは、割り当てで行われるmallocと割り当てられる場合、それは合法的であろう。

uint32_t arr; 
foo((struct element*)&arr, 5); // Possible pointer conversion issues still apply 

または

void * arr = malloc(4); 
foo(arr, 5); 

変換されたアドレスがuint32_t*型変数に格納することができない場合uint32_t* i = (uint32_t*)arrも、未定義の動作につながる可能性があることに注意してください。しかし、それは実装固有のであり、プラットフォームによって異なります。

+1

OPに「arr」に書き込むコードしか表示されていない場合、どうやってそれをUBと無条件に宣言できますか?適切に整列され、サイズが決められている場合は、書き込みに使用されているのと同じタイプを使用して常に読み取ることができます。 – alain

+0

これは別の質問のためのものかもしれませんが、最後の段落で作成したポイントを読むことができるリンクを私に撃つことができますか?私は、すべてのポインタが同じサイズであるという印象を受けました(関数ポインタを除く)。 ty。 – jayjay

+0

@ n.m。 Alはい、arrの格納タイプが 'struct element 'であると仮定してください。 – jayjay

3

であると仮定すると

。あなたは

uint32_t value = *(uint32_t*)arr; 

arrはどちらか(mallocを使用して)動的に割り当てられた、または自動記憶域期間を持つint32_tオブジェクトとして割り当てられていたとして、それを読まれる場合は

は 、(「スタック上」)それはOKです。
この場合、有効なタイプはint32_tに変更されます。
しかし、文字型ではなくuint32_tとは無関係の型を使用して読み込みたい場合は、未定義の動作です。

また、arrint32_tのために正しく調整する必要があります。 (。それはmallocを使用して得られた場合、それが自動的にある)


質問が編集された後、それは次のようにarrが割り当てられているので、それは、確かに未定義の動作であることが明らかになった:

struct element arr[4] __aligned(4); 
+0

なぜ@ n.m。正しく整列されサイズが決められていれば、 'int32_t'と読み替えるとメモリを再利用して' int32_t'を保存できますか? – alain

+0

残念ながら、関数が格納されていません。 –

+0

私は最初にそれを逃しました:) – alain

関連する問題