尝试将指针指向函数中的指针时的Segfault

我正在尝试使用数组(malloc-ed),即自定义结构的arr 。 通过引用函数传递数组。 每当我在运行时尝试索引除函数中的arr[0]以外的任何东西时,我会得到一个段错误(例如(*arr[1])->i = 3; )。 为什么会这样?

完整的源代码是:

 #include  #include  #define SIZE 100 typedef struct{ int i; float f; }foo; void doSomething(foo ***arr); int main() { foo **arr = (foo**) malloc (SIZE * sizeof(foo*)); int i; for(i = 0; i i = 1; printf("Before %d\n",arr[1]->i ); doSomething(&arr); printf("After %d\n",arr[1]->i ); return 0; } void doSomething(foo ***arr) { (*arr[1])->i = 3; } 

你的问题就在于此

 (*arr[1])->i = 3; 

由于下标运算符的评估先于解除引用的评估,因此它等同于以下内容:

 (*(arr[1]))->i = 3; 

这显然是错误的。 你需要

 (*arr)[1]->i = 3; 

因此。


笔记:

  • 不要malloc的结果
  • 添加#include 来解决警告
  • 添加额外级别的间接( foo***指向foo** )是不必要的; 只是按价值复制
  • (除了上面的注释)一个好的旧1D数组实际上应该足够了

  • malloc之后free拨打电话

你得到的警告是因为你忘了#include ,所以没有声明malloc ,所以编译器假定它应该返回int 。 这可能会导致各种有趣的问题。 (你应该删除那些演员。)


另一个问题是这一行: (*arr[1])->i = 3;

后缀运算符(如[] )绑定比前缀运算符更紧(如* ),因此*arr[1]解析为*(arr[1])

您可以编写(*arr)[1]->i来修复此问题,但事实certificate,您的函数实际上从未修改过*arr ,因此没有理由传递arr (另一个arr ,主要的那个)的地址。 这样做:

 void doSomething(foo **arr) { arr[1]->i = 3; } 

并称之为doSomething(arr)