为什么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上编译代码时,它会

我有一个简单的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上编译代码时,它会给我一个警告:

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请参见编辑-希望它能让事情更清楚一些。我明白了,我想我将研究数组和指针存储之间的区别。非常感谢。