6

だから、私は完全に慣れていないので、Cポインターとポインター演算で遊んでいました。このコードを思いつきました。

char* a[5] = { "Hi", "My", "Name", "Is" , "Dennis"};
char** aPtr = a; // This is acceptable because 'a' is double pointer
char*** aPtr2 = &aPtr; // This is also acceptable because they are triple pointers
//char ***aPtr2 = &a // This is not acceptable according to gcc 4.8.3, why ?

//This is the rest of the code, the side notes are only for checking
printf("%s\n",a[0]); //Prints Hi
printf("%s\n",a[1]); //Prints My
printf("%s\n",a[2]); //Prints Name
printf("%s\n",a[3]); //Prints Is
printf("%s\n",a[4]); //Prints Dennis

printf("%s\n",*(a+0)); //Prints Hi
printf("%s\n",*(a+1)); //Prints My
printf("%s\n",*(a+2)); //Prints Name
printf("%s\n",*(a+3)); //Prints Is
printf("%s\n",*(a+4)); //Prints Dennis

printf("%s\n",*(*(aPtr2) +0)); //Prints Hi 
printf("%s\n",*(*(aPtr2) +1)); //Prints My // ap = a, *ap = *a, *(ap)+1 = *a+1 ?
printf("%s\n",*(*(aPtr2) +2)); //Prints Name
printf("%s\n",*(*(aPtr2) +3)); //Prints Is
printf("%s\n",*(*(aPtr2) +4)); //Prints Dennis

char*** aPtr2 = &agcc 4.8.3 によれば受け入れられないのはなぜですか?

コンパイラの警告を追加するのを忘れて申し訳ありません:

警告: 互換性のないポインター型からの初期化 [デフォルトで有効]

私が言おうとしていることが不明確かもしれないので、次のリンクを追加する必要がありました:

コメントアウトされた行に注意してください。

4

2 に答える 2

2

a5ptrsのバッファのアドレスであり、不変です(つまり、固定ptrです)。許せば

char ***aPtr2 = &a;

それから

*aPtr2 = &a[3];

実際にアドレスを変更しますa(これは禁止されています)。

于 2015-06-01T18:11:34.120 に答える
1

これは、C が配列とアドレスを処理する方法に由来します。

int a[5];

aは true 型int * constです。つまり、ポインターが必要な場所で使用できます。ただし、スタックでは、ポインター用のスペースは割り当てられず、5 つの int 用のスペースのみが割り当てられます。意味aは と同じ&a[0]です。これはすべて予想どおりですが、奇妙な部分があります。

aと同じ&aです。これは、ポインタがどこにも保存されていないためです。そのアドレスを取得することはできません。しかし、コンパイルに失敗する代わりに、C 標準はそれらが同じであると言っているだけなので、一部の演算は機能します。

ただし、 を実行しているためchar ***aPtr2 = &a;、実質的に を実行しているchar ***aPtr2 = a;ため、segfault が発生します。トリプルポインターではなく、ダブルポインターのみです。

デバッガーですべての値を調べてより明確に確認するか、次のようなプログラムを実行できます。

#include <stdio.h>

int main(void)
{
    char *a[5] = { "Hi", "My", "Name", "Is" , "Dennis"};
    char **aPtr = a; 
    char ***aPtr2 = &aPtr;
    char ***aPtr3 = &a; 

    printf("%p %c\n", a, *a);
    printf("%p %p %c\n", aPtr, *aPtr, **aPtr);
    printf("%p %p %p %c\n", aPtr2, *aPtr2, **aPtr2, ***aPtr2);
    printf("%p %p %c\n", aPtr3, *aPtr3, **aPtr3);

    return 0;
}

出力を生成します:

0xfff65578 H
0xfff65578 0x8048648 H
0xfff65574 0xfff65578 0x8048648 H
0xfff65578 0x8048648 H

編集: もう 1 つの興味深い点は、関数ポインターが同じ方法で処理されることです。&funcと同じfuncです。

int add(int a, int b) { return a + b; }
typedef int (*PFUNC)(int, int);

PFUNC p1 = add;
PFUNC p2 = &add;
if (p1 == p2) 
     printf("Huh. %d, %d\n", (*p1)(1,2), p2(3, 4)); // the dereference is also optional
于 2015-06-01T18:18:50.250 に答える