2
#include <stdio.h>
void SetupAll(int *iPtr, int **p, int ***pp, int ****ppp){
   *p = iPtr;
   **pp =iPtr;
   ***ppp = iPtr;
   printf("hi\n");
}

int main() {
   int i = 42, *p, **pp, ***ppp;
   SetupAll(&i, &p, &pp, &ppp);
   printf("%u %u %u %u\n", ***ppp, **pp, *p, i);
}

为什么当我在没有 ppp(三重指针)的情况下运行这段代码时,它运行得非常好并且打印了 42 三次。但是,当我包含三重指针时,我从 SetupAll 函数中得到一个段错误。在我看来,ppp 遵循与获取 i 的其他两个指针相同的格式。帮助?

4

2 回答 2

4

它崩溃是因为您在初始化它们之前取消引用指针。即使你没有遇到同样的问题ppp——你只是很幸运,它并没有以某种方式崩溃。

您打算执行以下操作:

#include <stdio.h>
void SetupAll(int *iPtr, int **p, int ***pp, int ****ppp){
   *p = iPtr;
   *pp = p;
   *ppp = pp;
   printf("hi\n");
}

int main() {
   int i = 42, *p, **pp, ***ppp;
   SetupAll(&i, &p, &pp, &ppp);
   printf("%u %u %u %u\n", ***ppp, **pp, *p, i);
}

请注意 SetupAll 中的区别——您只取消引用每个指针一次,以便您可以设置它的值。声明中的其余“星”告诉您指针指向的事物类型。

编辑:详细说明,当你这样做时**pp,你实际上是在做*(*pp)——换句话说(a)首先找到*pp它本身就是一个指向 int 的指针的值,然后(b)尝试找到指向 int 的*pp值. 但是在您的原始代码中,您还没有初始化*pp,所以它随机指向某个地方。因此,在 (b) 处,当您尝试查找 int 的值时,如果返回的随机值*pp不是有效的内存地址,您很容易崩溃。

于 2013-05-10T01:49:11.603 回答
0

使用 valgrind 调试此问题会很有帮助,这是一种用于揭露内存错误的工具。

用调试符号编译它并在 valgrind 下运行它:

$ cc test.c -o test -g 
$ valgrind ./test 
[...]
Use of uninitialised value of size 8
   at 0x100000E85: SetupAll (test.c:4)
   by 0x100000ED3: main (test.c:11)
Invalid write of size 8
   at 0x100000E85: SetupAll (test.c:4)
   by 0x100000ED3: main (test.c:11)
Address 0x0 is not stack'd, malloc'd or (recently) free'd

第 4 行是这样的:

   **pp =iPtr;

因此,您可以看到 valgrind 在您尝试取消引用*p(一个未初始化的值)时终止了程序。

于 2013-05-10T02:17:51.950 回答