关于双指针和三指针/双维数组

时间:2015-06-01 17:40:29

标签: c pointers pointer-to-pointer

所以,我正在玩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
根据gcc 4.8.3,

char*** aPtr2 = &a是不可接受的,为什么?

抱歉忘了添加编译器警告:

  

警告:从不兼容的指针类型初始化[默认启用]

我可能不清楚我想说什么,所以我不得不添加这些链接:

注意注释掉的行。

2 个答案:

答案 0 :(得分:2)

a是5 ptrs的缓冲区的地址,并且是不可变的(即它是固定的ptr)。如果你允许的话

char ***aPtr2 = &a;

然后

*aPtr2 = &a[3];

实际上会修改地址a(这是禁止的)。

答案 1 :(得分:1)

这来自C处理数组和地址的方式:

int a[5];

a的类型为int * const,为true,这意味着您可以在需要指针的地方使用它。但是,在堆栈上没有分配指针的空间,只有五个整数的空间。含义a&a[0]相同。这是所有预期的,但这里有一个奇怪的部分:

a&a相同。这是因为指针没有存储在任何地方,你无法得到它的地址。但是没有使编译失败,C标准只是说它们是相同的,所以有些算法会起作用。

但是,由于您正在执行char ***aPtr2 = &a;,因此您实际上正在执行char ***aPtr2 = a;,这就是您遇到段错误的原因。它只是一个双指针,而不是三指针。

您可以检查调试器中的所有值以更清楚地查看它,或运行如下程序:

#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

编辑:另一个有趣的事情是函数指针以相同的方式处理。 &funcfunc相同。

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