C中动态内存分配的地址行为

时间:2018-06-15 20:59:20

标签: c pointers variables dynamic

我写了以下两个代码,分别给出了它们的输出。

代码1:

#include<stdio.h>
int* allocate(int array, int value)
{
    int k[array];
    //int *k=(int *)malloc(array*sizeof(int));
    for(int i=0;i<array;i++)
    {
        k[i]=value;
        printf("%d ",k[i]);
    }
    printf("\n");
    return k;
}
int main(void)
{
    int *p=allocate(3,25);
    for(int i=0;i<3;i++)
        printf("%d ",p);
    return 0;
}

输出:

25 25 25
0 0 0

代码2:

#include<stdio.h>
int* allocate(int array, int value)
{
    //int k[array];
    int *k=(int *)malloc(array*sizeof(int));
    for(int i=0;i<array;i++)
    {
        k[i]=value;
        printf("%d ",k[i]);
    }
    printf("\n");
    return k;
}
int main(void)
{
    int *p=allocate(3,25);
    for(int i=0;i<3;i++)
        printf("%d ",p);
    return 0;
}

输出:

25 25 25
12329552 12329552 12329552

据我所知,在第一个代码中,数据是在堆栈中分配的,一旦执行了return语句,编译器就会清除它。但我只是打印'p'而不是'* p'。为什么显示0?毕竟,指针* p在main()中声明。

请简单解释一下。提前致谢。

编辑1:我正在添加新代码以使我的问题清楚。 代码3:

#include<stdio.h>
int* allocateArray(int size, int value)
{
int arr[size];
for(int i=0; i<size; i++) {
arr[i] = value;
}
return arr;
}

int main(void)
{
    int* vector = allocateArray(5,45);
for(int i=0; i<5; i++) {
printf("%d\t", &vector[i]);
}
    return 0;
}

输出:

0 4 8 12 16

在第三个代码中,我无法打印vector [i]或*(vector + i)。编译器终止程序。

0的解释和第三个代码输出中的模式就是我所需要的。

1 个答案:

答案 0 :(得分:1)

在你的回答中,你解释说你明白你在allocate中返回指向不再存在的数组的指针,然后才将指针分配给p { {1}},并且想知道为什么返回空指针而不是例如“现实”堆栈指针。

为什么允许main

正如评论中所解释的那样,您的编译器也知道指针在检查时不会有效,因此可以返回空指针,因为以下规则:

  

来自ISO / IEC 9899:2011第6.2.4节
  指针的值在它指向(或刚刚过去)的对象到达其生命周期结束时变为不确定

通过不确定,这意味着这样的指针的值将是未指定或可能是陷阱表示(如果通过任何操作读取,则会导致未定义的行为),这意味着一个空指针可以返回,还有一个指向另一个现有对象的指针,一个指向没有对象的指针,以及一个可能导致程序崩溃或意外行为的指针值。

为什么编译器选择NULL

至于为什么编译器实现决定了一个空指针,可能是因为它是一个不太可能无声地破坏你的程序的选择。编译器通常不会影响性能以使您免于自己,但是在此处完全自由地优化前面的大部分功能并简单地返回一个空指针,如果它被解除引用,它将在典型的托管环境中导致立即的段错误,而不是允许通过尝试使用'已分配'数组来覆盖内存中的其他对象。