我正在使用一个指针数组,其中每个索引都包含一个指向整数数组的指针。虽然我能够弄清楚如何使用指针数组在数组中打印值,但是我需要澄清一行代码。我想了解**(x + i)和*(* x + i)之间的区别,因为前者引发了Segmentation Fault异常,而后者则输出了所需的输出。请参考下面的示例代码。
int pointer_array=malloc(1*sizeof(int*));
int number_array = malloc(2*sizeof(int));
*(pointer_array)=number_array;
for(int i=0;i<2;i++) {
*(pointer_array+i)=i;
}
for(int i=0;i<2;i++) {
//printf("\n%d",**(pointer_arr+i)); This throws Segmentation Fault exception
printf("\n%d",*(*pointer_arr+i)); // This prints the desired output 0 \n 1
}
答案 0 :(得分:6)
如果我们通过使用*(a + i) == a[i]
等价及其推论*a == a[0]
将它们转换为数组符号,则表达式之间的区别将变得非常明显。
**(x + i)
是x[i][0]
,而*(*x + i)
是x[0][i]
。
在您的代码中,我们想要这样做:
#include <stdlib.h>
int **pointer_array = malloc(1*sizeof(int*));
^^
int *number_array = malloc(2*sizeof(int));
^
然后其余的代码就是这样:
*(pointer_array)=number_array; // pointer_array[0] = number_array
糟糕:循环将整数分配给指针:
for(int i=0;i<2;i++) {
*(pointer_array+i)=i; // pointer_array[i] = i
}
以上内容可能是number_array[i] = i
。
for(int i=0;i<2;i++) {
printf("\n%d",*(*pointer_arr+i)); // printf ... pointer_arr[0][i]
}
如果我们纠正第一个循环以初始化number_array
,那么第二个循环应检索这些值。
否则,我们将继续使用未初始化的值。
答案 1 :(得分:0)
**(x+i)
的意思是“求值x+i
,它将给出一个指针,然后读取其指向的值,这将给出另一个指针,然后读取其指向的值”,或等效地,x[i][0]
。 *(*x+i)
的意思是“求值x
,它将给出一个指针,然后读取它指向的值,这将给出另一个指针,然后向其添加i
,然后读取该值它指向”,或等效地为x[0][i]
。显然,这是非常不同的表达方式。
答案 2 :(得分:0)
您的代码不安全; malloc
将返回void *
—指针类型。您将结果存储在int
中。无法保证int
的大小足以存储void *
,并且实际上不会在当前的主要体系结构x86上使用。
话虽这么说
(x+i)
(如果x是指针)将求值为i*sizeof(*x) + x
。因此,它将求出一个指针,该指针在x后面是i个插槽; **(x+i)
因此将从x之后的i插槽读取指针,然后读取该指针指向的任何内容。因此,从指向数组的指针数组中,它将从第i
个数组中读取第一项。
位置:
*x+i
将从x
中读取一个指针,然后向其添加i * sizeof(** x); *(*x+i)
从那里读取一个指针并取消引用。因此,从指向数组的指针数组中,它将从第一个数组中读取第i
个项目。