Oracle® Solaris Studio 12.4: C ユーザーガイド

印刷ビューの終了

更新: 2014 年 12 月
 
 

5.4.3 例: 内部ポインタ

次の例のソースコードは、特定レベルの別名設定が内部ポインタを処理できないことを示します。内部ポインタの定義については、Table 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) の実行後、対になった次のメモリーアクセスは同じメモリー位置に接触します。

  • fp->f2 および bp->b2 は、同じメモリー位置にアクセスします

  • fp->f3 および bp->b3 は、同じメモリー位置にアクセスします

  • fp->f4 および bp->b4 は、同じメモリー位置にアクセスします

ただし、オプション 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 および bp->b2

  • fp->f3 および bp->b3

  • fp->f4 および bp->b4

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