2016-07-13 3 views
15

質問:このコードは厳密なエイリアシング規則に違反していますか?

  1. 以下、このコードは、厳密なエイリアシング規則に違反していますか?つまり、最初に他の型としてアクセスされたバッファにint*を介してアクセスするので、スマートコンパイラは00000(または他の厄介な効果)を印刷できますか?

  2. ない場合は、それを破る(ptr1がスコープに来るときそうptr2は、すでに定義されます)括弧の前にptr2のちょうど定義とinitializatonを動かすのでしょうか?

  3. もしそうでなければ、中括弧を削除します(したがって、ptr1ptr2は同じ範囲にあります)。

  4. 「はい」の場合、コードはどのように修正できますか?

ボーナス質問:コードはOKで、2または3のどちらかそれを破るない場合、それは厳しいエイリアシング規則壊れるので、それを変更する方法(例、ブレースループint16_tを使用するための変換) ?


int i; 
void *buf = calloc(5, sizeof(int)); // buf initialized to 0 

{ 
    char *ptr1 = buf;  
    for(i = 0; i < 5*sizeof(int); ++i) 
     ptr1[i] = i; 
} 

int *ptr2 = buf; 
for(i = 0; i < 5; ++i) 
    printf("%d", ptr2[i]); 

この特定のコードについての確認を探しているので、短い(ISH)、専門家の答えは、理想的には、最小限の標準引用符で、私が後だものです。私は、厳密なエイリアシング規則の長い説明の後ではなく、このコードに関連する部分だけです。そして、答えが上記の番号の付いた質問を明示的に列挙するなら、それは素晴らしいでしょう。

また、整数のトラップ値を持たない汎用CPUを想定し、intが32ビットと2の補数であるとしましょう。

答えて

13

いいえ、これはメモリが割り当てられ、文字型を使用して書き込まれたためです。

メモリはmallocを使用して割り当てられます。そのオブジェクトは、型がmallocで割り当てられているため、宣言されていません。したがって、オブジェクトには有効な型はありません。

次に、コードはcharタイプを使用してオブジェクトにアクセスし、変更します。タイプは、 charであり、効果的な型を有するいかなる目的は、は、コピーがこれと後続のアクセスのためにcharに有効なタイプを設定していないコピーされていないが、唯一の期間、charに有効なタイプを設定するようにアクセス。アクセス後、オブジェクトはもはや有効な型を持たない。

次に、タイプintを使用して、そのオブジェクトにアクセスし、読み取るだけです。オブジェクトが有効な型を持たないので、読み取りの間、 intになります。アクセス後、オブジェクトはもはや有効な型を持たない。 intが明らかに有効なタイプintと互換性があったため、動作が定義されています。

(値はintのトラップ表現ない読み取ると仮定。)


あなたもintと互換性のない文字以外のタイプを使用してオブジェクトにアクセスし、変更たならば、動作は未定義であろう。

のは、あなたの例は、(sizeof(float)==sizeof(int)を想定)されたとしましょう:

int i; 
void *buf = calloc(5, sizeof(float)); // buf initialized to 0 

{ 
    float *ptr1 = buf;  
    for(i = 0; i < 5*sizeof(float); ++i) 
     ptr1[i] = (float)i; 
} 

int *ptr2 = buf; 
for(i = 0; i < 5; ++i) 
    printf("%d", ptr2[i]); 

float sが書き込みの期間およびそれ以降のすべてのために、タイプfloatのとなりに書き込まれているオブジェクトの効果的なタイプ、それを変更しないオブジェクトへのアクセス。これらのオブジェクトがintによってアクセスされると、有効なタイプはfloatのままです。値は読み取られないためです。以前の書き込みfloatを使用すると、有効なタイプはfloatに設定され、このオブジェクトへの次回の書き込み(この場合は発生しませんでした)まで永続的に設定されました。タイプintfloatは互換性がありません、したがって動作は未定義です。


(以下のすべてのテキストがから引用されている:ISO:IEC 9899:201X)

(6.5式6)は、その格納された値にアクセスするためのオブジェクトの
有効なタイプでありますオブジェクトの宣言された型(存在する場合) 87)割り当てられたオブジェクトに宣言された型はありません。

(6.5式6)
値を文字タイプないタイプを持つ左辺値を通る宣言された型を持たないオブジェクトに格納されている場合には、左辺値のタイプが有効になりますそのアクセスのためのオブジェクトのタイプと、格納された値を変更しない後続のアクセスのためのオブジェクトのタイプ。

ない宣言された型を持たないオブジェクトへの他のすべてのアクセスについて(6.5式6)
、オブジェクトの有効なタイプは、単にアクセスに使用左辺のタイプです。 - オブジェクトの有効な種類と互換性のあるタイプ88) :(6.5式8)
オブジェクトのみ 次のタイプの1つを有する左辺値表現によってアクセスその格納された値を持たなければならない

- オブジェクトの有効な型と互換性のある型の修飾バージョン - オブジェクトの有効な型に対応する符号付きまたは符号なし型である型 - 符号付きまたは符号なし型である型オブジェクトの有効なタイプ の修飾バージョンに対応して、

(6。5式6)
memcpyまたはmemmoveを使用して宣言された型を持たないオブジェクトに値がコピーされるか、または文字型の配列としてコピーされた場合、そのアクセスのための変更されたオブジェクトの有効な型と、値を変更しないは値がコピーされているオブジェクトの有効なタイプです(存在する場合)。

+0

あなたは暗黙のうちに、私が考えていなかった興味深い点を挙げています:割り当てられたメモリは 'int'値によって割り当てられていないので、6.5段落6の' int' 'int *'で逆参照されるため、結局は厳密なエイリアシングに違反しますか?そのパラグラフを解析するのは辛いです。 –

+1

この時点で、オブジェクトには文字だけが書き込まれ、有効な型はオブジェクトに設定されませんでした。宣言された型を持たないオブジェクトへの他のすべてのアクセスの場合、オブジェクトの実効型は単純にアクセスに使用される左辺値の型です* – 2501

+1

その同じ点で 'int 'が読み込みの代わりにオブジェクトに書き込まれていた場合、その型はまたint型になります:*型が文字型ではない型を持つlvalueを通して宣言型を持たないオブジェクトに格納されている場合、左辺の型がそのアクセスのためのオブジェクトの有効な型になり、格納された値を変更しない後続のアクセスのために* – 2501

2

いいえこれは厳密なエイリアシングに違反しません。 the C Standardから

6.2.5タイプ、段落28:

ポインタvoidには、文字型へのポインタと同じ表現と アライメント要件を持たなければなりません。 48

注48脚注を意味48:

48)と同じ表現と位置合わせ要件が関数の引数、関数から 戻り値、およびメンバーとして互換性を意味する を意味しています組合の

だから、問題なく(あなたptrptr1であることを意味すると仮定)char *ポインタを経由してcalloc() D」のメモリにアクセスすることができます。

それは本当に余分ですが、7.22.3メモリ管理機能いるので、第1項の状態:割り当てが成功した場合、ポインタが返さ

が適切ので それはへのポインタに割り当てることができることを揃えています次いで任意 基本整列要求を持つオブジェクトの種類とは、 オブジェクトまたはだから

を割り当てられたスペースにそのようなオブジェクトの配列にアクセスするために使用しますポインタとcharポインタを介してcalloc()のメモリに安全にアクセスできます。そして、double(あなたが割り当てられたメモリの境界内にとどまると仮定して)ブートのポインタ。

+6

厳密なエイリアシングは、位置合わせの要件と表現以外のものです。質問が参照している何JohannesSchaub - litb @ –

+1

は同じこと '符号なしchar' に変換'はmemset() 'ん(* ' memset' 機能コピー 'C' の値()でありますあなたがそれが間違っていると思うなら、 'memset()'がどのようなタイプを設定できるかを説明する答えを投稿してください。メモリを繰り返した 'char'値に置き換えます。 'memset()'が厳密な別名に違反していると言っていますか? –

+3

@AndrewHenle質問のコードが厳密なエイリアシング規則に違反しているとは誰も言いません。しかし、これがあなたの答えに示されている理由についての理論的根拠は正しくありません。同じ整列と表現を持つことは、2つの型がエイリアスになることを意味しません。 – davmac

関連する問題