繁体   English   中英

为什么在取消引用数组指针时 C 程序会崩溃?

[英]Why does C program crash when dereferencing pointer to an array?

我有一个简单的 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;
}

请向我解释,为什么当数组在堆上而不在堆栈上时代码有效?

为了让你的ptr变量成为“整数数组的地址”,你实际上需要一个更微妙(和神秘)的声明。

这将起作用:

int (*ptr)[10] = &test;

正如它声明的那样,当取消引用时(即当您实际使用表达式*ptr ),它将是一个数组(包含 10 个元素)。

在某些方面,声明的结构有点类似于函数指针的结构

编辑:在您的第二种情况下, test是一个普通的旧指针(由malloc调用分配给它的值); 因此,它本身就是一个可以获取其地址的变量(正如您的int **ptr = &test;行所做的那样 - 正确)。

但是,在第一种情况下(“固定”数组), test指的是一块内存; 在许多方面, this 可以用作指向第一个元素的指针(例如,就像在函数调用中一样)。 但是编译器可能会为“第一个元素的地址的地址”分配什么值? 这就是在这种情况下使用&test尝试分配失败的原因。

但是,根据上一段,您有权问,编译器如何使用此答案中给出的代码确定&test (分配给ptr )的值? 好吧,如果您将以下行添加到您的程序中:

printf("%p %p\n", test, &test);

您将看到test&test (您可以为ptr更改&test - 输出将相同)具有完全相同的值 因此,使用这个“神秘”声明,你给编译器足够的信息来知道如何处理“数组指针”——基本上,它有点“忽略”(或绕过)第一级解引用,以地址结束数组的第一个元素(按原样)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM