インテル® C++ コンパイラー XE 13.1 ユーザー・リファレンス・ガイド
コンパイラーがポインターの範囲情報を定義する方法について次に説明します。
各セクションで、lower_bound(p) は p に関連付けられている下限を指し、upper_bound(p) は p に関連付けられている上限を指します。
p = alloca(size); // lower_bound (p) = (char *)p // upper_bound (p) = lower_bound(p) + size - 1
p = calloc(num, size); // lower_bound(p) = (char *)p // upper_bound(p) = lower_bound(p) + size * num - 1
p = malloc(size); // lower_bound(p) = (char *)p // upper_bound(p) = lower_bound(p) + size - 1
p = (T *)q; // lower_bound(p) = lower_bound(q) // upper_bound(p) = upper_bound(q)
ポインターのキャストはポインターの範囲に影響しません。元のポインターに関連付けられている範囲よりも大きな新しい型にポインターをキャストした場合、元の範囲外のメンバーや要素にアクセスすると範囲外エラーが発生します。元のポインターよりも小さな型にポインターをキャストした場合、今までどおり元のデータにアクセスできます。
typedef struct { int num; int a[]; } T; q = malloc(sizeof(T) + sizeof(int) * num); p = &q->a; // lower_bound(p) = (char *)&q->a // upper_bound(p) = upper_bound(q)
配列を構造体の最後のメンバーとして定義する場合、上限は変更されず、malloc() 関数で割り当てられたすべての配列要素にアクセスできます。
p = &v; // lower_bound(p) = (char *)&v // upper_bound(p) = (char *)&v + sizeof(v) - 1 p = &v.m; // lower_bound(p) = (char *)&v + offsetof(typeof(v), m) // upper_bound(p) = lower_bound(p) + sizeof(v.m) – 1 p = &q->m; // lower_bound(p) = (char *)q + offsetof(typeof(*q), m) // upper_bound(p) = lower_bound(p) + sizeof(q->m) – 1
構造体、共用体、クラスのメンバーを指す場合、範囲情報はメンバーのサイズに変更されます。
p = new T; // lower_bound(p) = (char *)p // upper_bound(p) = lower_bound(p) + sizeof(T) - 1
T a[X][Y]; p = a; p = &a[x]; p = &a[x][y]; // lower_bound(p) = (char *)a // upper_bound(p) = lower_bound(p) + sizeof(a) - 1
配列の要素のアドレスまたは多次元配列の単一行のアドレスを使用する場合、範囲は要素のサイズに変更されません。配列全体のポインターをインクリメントまたはデクリメントすることができます。
p = &a[x][y].m; // lower_bound(p) = (char *)&a[n][m] + offsetof(T, m) // upper_bound(p) = lower_bound(p) + sizeof(T.m) – 1
要素のメンバーのアドレスを使用する場合、範囲はメンバーのサイズに変更されます。