2
#include<stdio.h>

int main()
{
  int *previous, *current ;
  int a[5] = {1,2,3,4,5};
  current =(int *) a ;
  previous = current ;
  current = *( (int**) current ) ; //my question is on this line

  printf ("\nprevious is 0x%x and current is 0x%x \n ", previous , current ) ;
  printf ("\nprev+1 0x%x ,  prev+4 0x%x \n", previous+1 , previous+4 ) ;
return 0;
}

出力は次のとおりです。

bash-3.00$ ./a.out

previous is 0xffffd0f8 and current is 0x1

prev+1 0xffffd0fc ,  prev+4 0xffffd108

私の質問は次のとおりです。「現在」は、参照されて再び逆参照される前に、以前は配列の先頭を指していました。次のステートメントは、「現在」の値をどのように変更しますか?

current = *( (int**) current ) ;

また、*previous を出力すると 1 が出力され、*current はコア ダンプします。この動作の理由は何ですか?

4

4 に答える 4

5
current = *( (int**) current ) ;

まず、 にキャストcurrentするため、から始まるバイトint**に格納されている値は、 のアドレスとして解釈されます。次に、キャストから取得したポインターを逆参照します。つまり、そこに格納されていると想定される が続き、そのアドレスのバイトが に格納されます。sizeof(int**)&currentint*int**sizeof(int*)current

ここでcurrent、配列 の最初の要素を指しているaため、 の先頭に格納されているバイトaが にコピーされcurrentます。の場合sizeof(int*) == sizeof(int)int格納されている値 1a[0]はアドレスとして解釈されます。If sizeof(int*) == 2*sizeof(int)(もう 1 つの一般的な発生) の場合、ポインター値は 2 つintの 1 と 2 で構成されます。

previousの最初の要素を指すため、a逆参照previousは値 1 を生成します。逆参照は、アドレス 1 からcurrentを読み取ろうとしますint(これは未定義の動作であるため、他に何が起こっても標準に違反することはありませんが、それが通常の過程です)。通常、プロセスではアクセスできません。

于 2012-11-27T11:26:09.320 に答える
2
current =(int *) a ;

current値を含むメモリアドレスを指している葉1。したがって

(int**) current

この1値自体をポインターとして扱い、当然のことながらセグメンテーション違反につながる逆参照を行います。

于 2012-11-27T11:26:10.147 に答える
1

これ

(int **) current

逆参照ではなく、これ

*(ptr)

参照していません。

逆参照

*current

参照する

&(ptr)

最終声明:

current = &(*current);
于 2012-11-27T11:40:48.540 に答える
0

それは非常に単純です。現在の逆参照をしているだけなので、

*((int**) current)

int* にキャストされた配列の最初の要素 (0x1) です。

システムの 99.9% では、このアドレスはユーザー プロセスによって読み取れないため、0x1 を逆参照すると明らかに segfault が発生します。

于 2012-11-27T11:30:15.167 に答える