将数组分配给具有复杂情况的指针

时间:2018-07-12 01:32:27

标签: c arrays pointers

如果我们将一个指针分配给另一个指针,则称为“交换指针”。例如,

float *temp, *ptr1, *ptr2;
temp = ptr1;
ptr1 = ptr2;
ptr2 = temp;

但是,如果我们将数组分配给指针,则是非法的,因为array并不是指针类型。但是,请看下面的3个示例:

float arr[]={1.2, 1.9, 3.1};
float *ptr;
int i;
ptr = (float *)calloc(3,sizeof(float));
ptr = arr;
for (i=0;i<3;i++){
    printf("ptr[%d]=%f\n",i,ptr[i]);
}

此代码段已通过编译并正确运行(非法代码获得正确答案?):

ptr[0]=1.200000
ptr[1]=1.900000
ptr[2]=3.100000

如果我在最后一行之后添加free(ptr),即

float arr[]={1.2, 1.9, 3.1};
float *ptr;
int i;
ptr = (float *)calloc(3,sizeof(float));
ptr = arr;
for (i=0;i<3;i++){
    printf("ptr[%d]=%f\n",i,ptr[i]);
}
free(ptr);  /*add free here*/

这一次出现警告:

warning: attempt to free a non-heap object ‘arr’ [-Wfree-nonheap-object]

int i;
int flag=0;
float arr1[3]={1.07,3.01,5.02};
float arr2[3]={2.07,6.01,9.02};
float arr3[3]={3.07,8.01,0.02};
float *ptr;
ptr = (float *)calloc(3,sizeof(float));
if(flag==0){
    ptr = arr1;
}
else if(flag==1){ 
    ptr = arr2;
}
else{ 
    ptr = arr3;
}
for (i=0;i<3;i++){
    printf("ptr[%d]=%f\n",i,ptr[i]);
}

它可以在不同的flag上正常运行,但是如果我在最后一行添加free(ptr),它仍然会像以前一样发出警告。

有人帮助分析原因吗?

4 个答案:

答案 0 :(得分:3)

ptr = (float *)calloc(3,sizeof(float));

在这里,您将ptr设置为一个足够大的可分配3个浮点数的已分配内存的块。然后在下一行:

ptr = arr;

使用ptr覆盖arr的值,导致内存泄漏。这是合法的,因为在这样的赋值中,数组衰变到指向其第一个元素的指针中。

然后打印ptr指向的值时,会在arr中得到值,因为ptr指向该位置。

这也是为什么在free上调用ptr无效的原因,因为它不再指向分配的内存。

对于代码的最后一部分,这是无效的初始化程序:

float arr1[3]={{1.07,3.01,5.02}};

运行此代码时,flag=0的第二个和第三个值显示为0,而flag=1flag=2则显示了所有预期值。

您只需要一组括号:

float arr1[3]={1.07,3.01,5.02};

答案 1 :(得分:2)

解决方案没有错误

#include<stdio.h>  
#include<stdlib.h>

int main()
{
    float arr[]={1.2, 1.9, 3.1};
    float *ptr;
    int i;
    ptr = (float *)calloc(3,sizeof(float*));

    if(ptr == NULL){
     perror("calloc");
     return -ENOMEM;
    }
    //ptr = arr;

    // here you need to do something like this
    ptr[0] = arr[0];
    ptr[1] = arr[1];
    ptr[2] = arr[2];

    for (i=0;i<3;i++){
       printf("ptr[%d]=%f\n",i,ptr[i]);

           }
        free(ptr);
}

答案 2 :(得分:1)

当您将指针指向数组时,代码中绝对没有任何非法行为。它甚至不会给您警告。

指针是一个指针,它可以指向任何东西。有时您可能需要强制转换,但指向相同基本类型的数组不仅完全有效,而且甚至很常见。

但是,您只能在堆上分配的内存(malloc,calloc等)上使用free。数组是在堆栈上分配的,不需要释放,正如您已经看到的那样,如果这样做,您将收到运行时错误。

答案 3 :(得分:1)

  

分配数组

在C数组中可能未分配。

您需要按元素分配元素。

这里会发生什么

float arr[]={1.2, 1.9, 3.1};
float *ptr;

ptr = arr;

是您将ptr的地址分配给arr[0]。称为“ The array is decayed to a pointer(它的第一个元素的地址)

没有数组元素被复制!

要证明这一点

arr[0] = 42.;

下一步,然后运行打印循环

for (int i = 0; i < 3; ++i) 
{
  printf("ptr[%d] = %f\n", i, ptr[i]);
}

您将得到(类似):

ptr[0] = 42.000
ptr[1] = 1.9000
...