为什么C程序在解引用指向数组的指针时崩溃?
我有一个简单的C代码:为什么C程序在解引用指向数组的指针时崩溃?,c,windows,pointers,mingw,double-pointer,C,Windows,Pointers,Mingw,Double Pointer,我有一个简单的C代码: int main() { int test[10] = {1,2,3,4,5,6,7,8,9,10}; int **ptr = &test; printf("%d\n", (*ptr)[0]); return 0; } 一旦到达printf行,它就会崩溃: Process returned -1073741819 (0xC0000005) execution time : 0.865 s 在Ubuntu上编译代码时,它会
int main()
{
int test[10] = {1,2,3,4,5,6,7,8,9,10};
int **ptr = &test;
printf("%d\n", (*ptr)[0]);
return 0;
}
一旦到达printf
行,它就会崩溃:
Process returned -1073741819 (0xC0000005) execution time : 0.865 s
在Ubuntu上编译代码时,它会给我一个警告:
test.c:8:17: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
int **ptr = &test;
但是,如果我改为在堆上动态分配内存,则代码可以工作:
int main()
{
int *test = malloc(sizeof(int)*10);
for (int i = 0; i < 10; i++) {
test[i]=i;
}
int **ptr = &test;
printf("%d\n", (*ptr)[1]);
return 0;
}
intmain()
{
int*test=malloc(sizeof(int)*10);
对于(int i=0;i<10;i++){
试验[i]=i;
}
int**ptr=&test;
printf(“%d\n”,(*ptr)[1]);
返回0;
}
请向我解释一下,为什么当数组在堆上而不是在堆栈上时,代码可以工作?为了让
ptr
变量成为“整数数组的地址”,实际上需要一个更微妙(更神秘)的声明
这将有助于:
int(*ptr)[10]=&test;
正如它声明的那样,当取消引用时(即当您实际使用表达式*ptr
),它将是一个数组(由10个元素组成)
在某些方面,声明的结构有点像
编辑:在第二种情况下,test
是一个普通的旧指针(其值由malloc
调用分配);因此,它本身就是一个可以获取其地址的变量(正如您的int**ptr=&test;
行所做的那样-正确)
然而,在第一种情况下(“固定”数组),test
指内存块;在许多方面,这可以用作指向第一个元素的指针(例如,它将在函数调用中使用)。但是编译器可以为“第一个元素的地址的地址”分配什么值呢?在这种情况下,使用&test
尝试分配失败
但是,根据上一段,您有权询问编译器如何使用此答案中给出的代码确定&test
(分配给ptr
)的值?好的,如果您在程序中添加以下行:
printf(“%p%p\n”、测试和测试);
您将看到
test
和&test
(您可以为ptr
更改&test
——输出将是相同的)具有完全相同的值!因此,使用这个“神秘”声明,您可以为编译器提供足够的信息来知道如何处理“数组指针”——基本上,它会“忽略”(或绕过)第一级解引用,最终得到数组第一个元素的地址(原样).main.c:5:11:警告:不兼容的指针类型使用类型为“int(*)[10]'[-Wincompatible pointer types]int**ptr=&test;的表达式初始化“int**”代码>[cquery]不兼容的指针类型使用类型为“int(*)[10]'[-Wincompatible指针类型]
的表达式初始化“int**”,无需编译…int*ptr=test代码>和printf(“%d\n”,ptr[0])
看起来更理智/更符合预期用例。仅供参考,int**ptr=&test代码>是无效的C。带有-pedantic errors
GCC在这里给出了一个错误。但是指向第一个元素的指针和数组之间有什么区别?[]访问不应该产生相同的结果吗?@Victor2748请参见编辑-希望它能让事情更清楚一些。我明白了,我想我将研究数组和指针存储之间的区别。非常感谢。