2012-02-01 7 views
2

addrは関数のパラメータであり、read_valueは関数のローカル変数です。どちらもint型です。ポインタの変数への代入

次に何をん:

read_value = (* (int *) (addr)) 

はどういう意味ですか?

答えて

1

addrをintへのポインタにキャストし、逆参照してread_valueに入れます。

addrが実際にはintの場合、それは未定義の動作だと思います。

+0

キャストの結果が表現できない値になるのは、未定義の動作のみです。 (C11 6.3.2.3参照)。 – Lundin

4

(int *) (addr)は、addrの数値をint *ポインタにキャストします。特別な注意が払われない限り、addrの任意の値がintのアライメント要件に違反する可能性があるため、この操作は安全ではありません。一般に、addrの値がintのサイズの倍数ではない場合、それは最終的にSIGBUS信号をもたらすことがある不整合読み取りにつながる可能性があります。

最後に、アスタリスクは、そのアドレスにあるint値(逆参照と呼ばれます)を取り出してread_valueに保存します。アドレスが十分に整列されていない場合、位置合わせ不良リードが発生するのはこの時点である。参照が制限されたり保護されたりすると、逆参照によってセグメント違反が発生する可能性があります。

ことがint *にキャストの間、より安全性を与えるので、私は実際には、むしろintよりも、タイプuintptr_tであることがaddrを宣言します。 uintptr_tは、ポインタのサイズと表現に対応する必要がありますが、intタイプは意味的にポインタと無関係です。

+1

ここに追加するだけで、このプラクティスは「型打ち」として知られています。そして言及したように、それは危険です。アライメントが分からない場合は、代わりに 'memcpy()'を使って 'int'値を読み込みます。 – FatalError

1

は、次の例を見てみましょう:

int read_value = 0; 
int address = 0x1234; 

read_value = *(int *) address; 

これは同等です:

read_value = *(int *) 0x1234; 

これはアドレス0x1234read_valueオブジェクトに格納しでintを読み込みます。 int0x1234を最初にintへのポインタに変換してから、ポインターを逆参照してintの値にアクセスすることによって行われます。

変換(int *) 0x1234は実装定義です。

(C99、6.3.2.3p5)「整数が先に指定された場合を除き、結果は実装定義され、正しく整列されないことがあります。任意のポインタ型に変換することができる、の実体を指していない可能性があります参照された型であり、トラップ表現である可能性があります。

そして、ポインタが間違っている場合、または正しい位置合わせがない場合、ポインタの逆参照は未定義の動作です。無効なポインタを使用すると、未定義の動作になります。無効なポインタは、nullではないが、適切なオブジェクトまたは関数を指していないポインタです。

関連する問題