間接演算子とアドレス演算子
単項間接演算子 (*) は、ポインターを介して値に間接的にアクセスします。 オペランドは、ポインター型である必要があります。 演算の結果は、オペランドによってアドレス指定される値です。つまり、オペランドがポイントするアドレスでの値です。 結果の型は、オペランドでアドレス指定する型です。
オペランドの型が pointer to type である場合、関節演算子の結果は type になります。 オペランドが関数を指している場合、結果は関数指定子になります。 オブジェクトを指している場合、結果はオブジェクトを指定する左辺値になります。
ポインター値が有効でない場合、間接演算子の結果は未定義になります。 ポインター値が無効になる一般的な条件をいくつか示します。
ポインターが null ポインターです。
ポインターが、参照時にその有効期間が終了しているオブジェクトのアドレスを指定しています。 (たとえば、スコープ外になったオブジェクトや割り当てが解除されたオブジェクトなど。)
ポインターが、ポイントしているオブジェクトの型に対して不適切にアラインされたアドレスを指定しています。
ポインターが、実行プログラムで使用されていないアドレスを指定しています。
単項アドレス演算子 ( & ) は、オペランドのアドレスを与えます。 オペランドは、次のいずれかである必要があります。
registerと宣言されておらず、ビット フィールドではないオブジェクトを指定する lvalue。単項逆参照 (
*) または配列逆参照 ([]) 演算子の結果。関数指定子。
結果は、"オペランドの型" という型のオペランドに対して "オペランドの型へのポインター" という型になります。
オペランドが単項 * 演算子の結果である場合、演算子は評価されず、両方が省略されたかのような結果になります。 結果は lvalue ではなく、演算子の制約は引き続き適用されます。 オペランドが [] 演算子の結果である場合、& 演算子も、[] 演算子によって暗黙的に指定される単項 * も評価されません。 結果は & 演算子を削除して [] 演算子を + 演算子に変更する場合と同じ効果があります。 それ以外の場合、結果はオブジェクトへのポインターまたは演算子によって指定された関数になります。
使用例
以下に挙げる例では、次の一般的な宣言を使用します。
int *pa, x;
int a[20];
このステートメントは address-of 演算子 ( & ) を使用して、配列 a の 6 番目の要素のアドレスを受け取ります。 結果は、ポインター変数 pa に格納されます。
pa = &a[5];
この例では、間接演算子 (*) は、pa に格納されているアドレスにある int 値にアクセスするために使用されます。 その値は整数変数 x に代入されます。
x = *pa;
この例では、x のアドレスに間接演算子を適用した結果が x と同じであることが示されます。
assert( x == *&x );
この例では、関数へのポインターを宣言するのと同じ方法を示しています。
int roundup( void ); /* Function declaration */
int *proundup = roundup;
int *pround = &roundup;
assert( pround == proundup );
関数 roundup を宣言した後、roundup への 2 つのポインターを宣言して、初期化しています。 最初のポインター、proundup は、関数名のみを使用して初期化され、2 番目のポインター、pround は、初期化時にアドレス演算子が使用されています。 これらの初期化は同じ意味を持ちます。