【问题标题】:Why does C program crash when dereferencing pointer to an array?为什么 C 程序在取消引用指向数组的指针时会崩溃?
【发布时间】:2020-05-12 09:25:12
【问题描述】:

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

请解释一下,为什么当数组在堆上而不是在栈上时代码可以工作?

【问题讨论】:

  • main.c:5:11: warning: incompatible pointer types initializing 'int **' with an expression of type 'int (*)[10]' [-Wincompatible-pointer-types] int **ptr = &amp;test;
  • [cquery] incompatible pointer types initializing 'int **' with an expression of type 'int (*)[10]' [-Wincompatible-pointer-types],不用编译...
  • int *ptr = test;printf("%d\n", ptr[0]); 似乎更理智/预期的用例。
  • 仅供参考,int **ptr = &amp;test; 无效 C。使用 -pedantic-errors 时,GCC 会出现错误。

标签: c windows pointers mingw double-pointer


【解决方案1】:

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

这将起作用:

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

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

在某些方面,声明的结构有点像pointers-to-functions

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

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

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

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

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

【讨论】:

  • 但是指向第一个元素的指针和数组有什么区别呢? [] 访问不应该产生相同的结果吗?
  • @Victor2748 查看编辑 - 希望它能让事情变得更清晰。
  • 我明白了,我想我会研究数组和指针存储之间的差异。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
  • 2019-05-23
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
相关资源
最近更新 更多