Oracle Solaris Studio 12.2: C ユーザーガイド

5.4.3 例 3

次の例のソースコードは、特定レベルの別名設定が内部ポインタを処理できないことを示します。内部ポインタの定義については、表 B–13 を参照してください。

struct foo {
        int f1;
        struct bar *f2;
        struct bar *f3;
        int f4;
        int f5;
        struct bar fb[10];
} *fp;

struct bar
        struct bar *b2;
        struct bar *b3;
        int b4;
} *bp;

bp=(struct bar*)(&fp->f2);

この例の参照解除は、weaklayoutstrict、または std でサポートされません。ポインタ割り当て bp=(struct bar*)(&fp->f2) の実行後、対になった 次のメモリーアクセスは同じメモリー位置に接触します。

ただし、オプション weaklayoutstrict、および std を指定する場合、コンパイラは、fp->f2 および bp->b2 が別名設定しないことを仮定します。コンパイラがこのように仮定する理由は、b2 のオフセットが 0 である一方で f2 が 4 バイトのオフセットを保持することと、foo および bar が共通の初期シーケンスを保持しないことにあります。同様に、コンパイラは、bp->b3fp->f3 を別名設定しないこと、および bp->b4fp->f4 を別名設定しないことも仮定します。

そのため、ポインタ割り当てbp=(struct bar*)(&fp->f2) により、別名情報に関するコンパイラの仮定が正しくない状況が作成されます。これにより、最適化が正しく行われない可能性があります。

次の例に示されている変更を行なったあとで、コンパイルを実行してください。


struct foo {
        int f1;
        struct bar fb;   /* Modified line */
#define f2 fb.b2         /* Modified line */
#define f3 fb.b3         /* Modified line */
#define f4 fb.b4         /* Modified line */
        int f5;
        struct bar fb[10];
} *fp;

struct bar
        struct bar *b2;
        struct bar *b3;
        int b4;
} *bp;

bp=(struct bar*)(&fp->f2);

ポインタ割り当て bp=(struct bar*)(&fp->f2) の実行後、対になった 次のメモリーアクセスは同じメモリー位置に接触します。

前述のコード例に示された変更内容を調べることにより、式 fp->f2 が式 fp->fb.b2 のもう 1 つの書式であることが理解できます。fp->fb の型が bar であるため、fp->f2barb2 フィールドにアクセスします。さらに、bp->b2barb2 フィールドにアクセスします。そのため、コンパイラは、fp->f2bp->b2 を別名設定することを仮定します。同様に、コンパイラは、fp->f3bp->b3 を別名設定し、fp->f4bp->b4 を別名設定することも仮定します。その結果、コンパイラの仮定する別名設定は、ポインタ割り当てで設定された実際の別名と一致します。