6.5.6加法演算子の下:
セマンティクス
8-[...]ポインタオペランドが配列オブジェクトの要素を指し、配列が十分に大きい場合、結果は元の要素からオフセットされた要素を指し、結果と元の添え字の差が配列要素は整数式と同じです。[...]結果が配列オブジェクトの最後の要素の1つ過ぎを指している場合、*
評価される単項演算子のオペランドとして使用されないものとします。
それまでにメモリが割り当てられているmalloc
場合:
7.22.3メモリ管理機能
1-[...]割り当てが成功した場合に返されるポインタは、基本的な配置要件を持つ任意のタイプのオブジェクトへのポインタに割り当てられ、そのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用できるように、適切に配置されます。割り当てられたスペース内(スペースが明示的に割り当て解除されるまで)。割り当てられたオブジェクトの存続期間は、割り当てから割り当て解除まで延長されます。
ただし、これは適切なキャストなしでそのようなメモリの使用を考慮しないため、MyStruct
上記で定義されているように、オブジェクトの宣言されたメンバーのみを使用できます。これが、柔軟な配列メンバー(6.7.2.1:18)が追加された理由です。
また、付録J.2の未定義動作は、配列アクセスを呼び出すことに注意してください。
1-次の状況では、動作は定義されていません。[...]
—配列オブジェクトおよび整数型への、またはそのすぐ先へのポインターの加算または減算により、同じ配列オブジェクト。
—配列オブジェクトおよび整数型への、またはそのすぐ先へのポインターの加算または減算は、配列オブジェクトのすぐ先を指す結果を生成し、*
評価される単項演算子のオペランドとして使用されます。
—指定された添え字でオブジェクトに明らかにアクセスできる場合でも(a[1][7]
宣言で指定された左辺値式のように)、配列の添え字が範囲外ですint
a[4][5])
。
したがって、お気づきのように、これは未定義の動作になります。
MyStruct *foo = malloc(sizeof(MyStruct) + sizeof(int) * 10);
foo->data[5] = 1;
ただし、次のことを行うことができます。
MyStruct *foo = malloc(sizeof(MyStruct) + sizeof(int) * 10);
((int *) foo)[(offsetof(MyStruct, data) / sizeof(int)) + 5] = 1;
C ++は、この点で緩いです。3.9.2複合タイプ[basic.compound]には次のものがあります。
3-[...]型のオブジェクトがT
アドレスにある場合、値がアドレスA
である型のポインタは、値がどのように取得されたかに関係なく、そのオブジェクトを指していると言われます。cv T*
A
restrict
これは、たとえば修飾子を使用した、ポインターに対するCのより積極的な最適化の機会に照らして検討するのが理にかなっています。