1
main()
{
int a[]={5,4,3,2,1};
int *p[]={a,a+1,a+2,a+3,a+4 };
int **ptr=p;//what does it really means
cout<<a<<*a;/*prints the address of a, value of a[0] (i understand this line)*/
cout<<endl<<p<<*p<<**p;/*prints the address of p, address of a, value of a[0]    (understands this line's logic too)*/
cout<<endl<<ptr<<*ptr<<**ptr;\*this line's o/p is same as the previous one cant   understand why*/
}

**ptr の意味と、3 行目の出力が 2 行目と同じである理由を説明してください。

そしてもう1つの疑問:

  1. int *ptr=(char *)0;
  2. float *ptr=(float *)0;
  3. char *ptr=(char *)0;

これらはすべて (char *) が表すヌル ポインターの表現であるという記事を読みました。

4

3 に答える 3

3

配列は、そこで使用している式のコンテキストを含む、いくつかのコンテキストで最初の要素へのポインターに崩壊します。これらの行のいくつかで、それ自体では&array[0]なく明示的に使用すると、より意味のあるものになるでしょう。arrayまず、次の宣言ptr:

int **ptr = p;     // ptr is a pointer to the first element of p
int **ptr = &p[0]; //   and this expression is equivalent.

次に、pand friends の印刷 - 繰り返しますが、両方の表現は同じです。

cout << endl << p << *p << **p;
cout << endl << &p[0] << *&p[0] << **&p[0];

さて、ptr行の印刷 - ptris&p[0]であるため、両方の行が同等であることがわかります。

cout << endl << ptr << *ptr << **ptr;
cout << endl << &p[0] << *&p[0] << **&p[0];

そして、そこにある 2 行目は、すぐ上の 2 行目と同じです。したがって、同じ出力が得られます。

comp.lang.cFAQ セクション 6, Arrays and Pointersを読むと役立つ場合があります。

于 2013-06-15T21:27:06.760 に答える
1
int **ptr=p

intへのポインタへのポインタ

int *p[] は、ポインターの配列、int 配列のアドレスを例に保持します。

あなたの例で同じ出力の理由。**ptr と *p[0] ara は同じです。* ptr == * (ptr +0) == ( (p+0)) == **p //all は配列 a の 0 番目の要素を指します。

于 2013-06-15T21:23:40.103 に答える
-1

http://www.eskimo.com/~scs/cclass/int/sx8.htmlから取得:

` int へのポインタ、 char へのポインタ、定義した任意の構造体へのポインタ、そして実際には C の任意の型へのポインタを持つことができるので、ポインタを持つことができることはそれほど驚くべきことではありません他のポインターへ。単純なポインターについて考えることに慣れていて、ポインター自体とそれが指している対象との区別を頭の中で明確にしておくことに慣れている場合は、ポインターへのポインターについても考えることができるはずですが、今はそうしなければなりません。ポインター、それが指すもの、およびポインターが指すポインターが指すものを区別します。(そしてもちろん、ポインターへのポインターへのポインター、またはポインターへのポインターへのポインターへのポインターになる可能性もありますが、これらは急速に難解になりすぎて実用的ではなくなります。) ポインターからポインターへの宣言は次のようになります。 int **ipp; のように。ここで、2 つのアスタリスクは、2 つのレベルのポインターが関係していることを示します。おなじみの、刺激の少ない幼稚園スタイルの例から始めて、 ipp が指すポインターと、それらのポインターが指す int を宣言することにより、 ipp の使用法を示すことができます。

int i = 5, j = 6; k = 7;
int *ip1 = &i, *ip2 = &j;

これで設定できます

ipp = &ip1;

ipp は、i を指す ip1 を指します。*ipp は ip1 であり、**ipp は i または 5 です。

...

実際には、ポインターへのポインターは何に適していますか? 1 つの使用法は、正式な戻り値としてではなく、ポインター引数を介して、関数からポインターを返すことです。これを説明するために、まず一歩戻って、ポインター引数を介して関数から int などの単純な型を返す場合を考えてみましょう。関数を書くと

f(int *ip)
{
*ip = 5;
}

そして、次のように呼び出します。

int i;
f(&i);

f は、呼び出し元から渡されたポインターによって指定された場所に値 5 を書き込むことにより、値 5 を返します。この場合、呼び出し元の変数 i に。関数は、返すものが複数ある場合、この方法で値を返す可能性があります。これは、関数は 1 つの正式な戻り値しか持てない (つまり、return ステートメントを介して 1 つの値しか返せないため) ためです。注意すべき重要なことは、関数が int 型の値を返すために、int 型へのポインタのパラメータを使用していました。ここで、関数がこの方法でポインターを返したいとします。対応するパラメーターは、ポインターへのポインターである必要があります。たとえば、長さ n の文字列にメモリを割り当てようとする小さな関数を次に示します。この関数は、失敗した場合は 0 (false") を返し、成功した場合は 1 (ゼロ以外、または true") を返します。

#include <stdlib.h>
int allocstr(int len, char **retptr)
{
char *p = malloc(len + 1); /* +1 for \0 */
if(p == NULL)
return 0;
*retptr = p;
return 1;
}

呼び出し元は、次のようなことができます

char *string = "Hello, world!";
char *copystr;
if(allocstr(strlen(string), &copystr))
strcpy(copystr, string);
else fprintf(stderr, "out of memory\n");

(これはかなり大雑把な例です。allocstr 関数はあまり役に立ちません。呼び出し元が malloc を直接呼び出すのと同じくらい簡単だったでしょう。malloc の周りにラッパー関数を記述する別の、より便利な方法は次のとおりです。これまで使用してきた chkmalloc 関数がその例です。) `

于 2013-06-15T21:26:38.413 に答える