简体   繁体   English

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

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

I have a simple C code:我有一个简单的 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;
}

As soon as it reaches the printf line, it crashes:一旦到达printf行,它就会崩溃:

Process returned -1073741819 (0xC0000005)   execution time : 0.865 s

When compiling the code on Ubuntu, it gives me the warning:在 Ubuntu 上编译代码时,它给了我警告:

test.c:8:17: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
     int **ptr = &test;

However, if I instead dynamically allocate the memory on the heap, the code works:但是,如果我改为在堆上动态分配内存,则代码有效:

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;
}

Please explain to me, why the code works when the array is on the heap, but not on the stack?请向我解释,为什么当数组在堆上而不在堆栈上时代码有效?

In order to get your ptr variable to be the "address of an array of integers" you actually need a rather more subtle (and arcane) declaration.为了让你的ptr变量成为“整数数组的地址”,你实际上需要一个更微妙(和神秘)的声明。

This will work:这将起作用:

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

as it declares that, when dereferenced (ie when you then actually use the expression *ptr ), it will be an array (of 10 elements).正如它声明的那样,当取消引用时(即当您实际使用表达式*ptr ),它将是一个数组(包含 10 个元素)。

In some ways, the structure of the declaration is a bit like that for pointers-to-functions .在某些方面,声明的结构有点类似于函数指针的结构

EDIT: In your second case, test is a plain old pointer (with a value assigned to it by the malloc call);编辑:在您的第二种情况下, test是一个普通的旧指针(由malloc调用分配给它的值); as such, it is itself a variable whose address can be taken (as your int **ptr = &test; line does - correctly).因此,它本身就是一个可以获取其地址的变量(正如您的int **ptr = &test;行所做的那样 - 正确)。

However, in the first case ('fixed' array), test refers to a block of memory;但是,在第一种情况下(“固定”数组), test指的是一块内存; in many ways, this can be used as a pointer to the first element (like it will be in a function call, for example).在许多方面, this 可以用作指向第一个元素的指针(例如,就像在函数调用中一样)。 But what value can the compiler possibly assign to the "address of the address of the first element?"但是编译器可能会为“第一个元素的地址的地址”分配什么值? This is what fails in the attempted assignment using &test in this case.这就是在这种情况下使用&test尝试分配失败的原因。

But, you would be entitled to ask, according to the previous paragraph, how does the compiler determine a value for &test (to assign to ptr ) with the code given in this answer?但是,根据上一段,您有权问,编译器如何使用此答案中给出的代码确定&test (分配给ptr )的值? Well, if you add the following line to your program:好吧,如果您将以下行添加到您的程序中:

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

you will see that test and &test (you can change &test for ptr - the output will be the same) have exactly the same value !您将看到test&test (您可以为ptr更改&test - 输出将相同)具有完全相同的值 Thus, using this 'arcane' declaration, you give the compiler enough information to know what to do with the "array pointer" - basically, it sort of 'ignores' (or bypasses) the first level of dereferencing, ending up with the address of the array's first element (as is).因此,使用这个“神秘”声明,你给编译器足够的信息来知道如何处理“数组指针”——基本上,它有点“忽略”(或绕过)第一级解引用,以地址结束数组的第一个元素(按原样)。

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

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