Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign an array to a pointer with complex cases

Tags:

arrays

c

pointers

if we assign a pointer to another pointer, it's called "swap the pointers". For example,

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

However, if we assign an array to a pointer, it's illegal because array is not really the pointer type. But look at the next 3 examples:

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

This code snippet passed the compilation and ran correctly (illegal code gets the correct answer?):

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

If I add free(ptr) following the last line, i.e.

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*/

This time a warning came up:

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

It can run correctly with different flag, but if I add free(ptr) at last line, it still has warning like the previous.

Does anybody help analyze why?

like image 567
coco Avatar asked Dec 04 '25 23:12

coco


2 Answers

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

Here, you set ptr to a block of malloc'ed memory big enough for 3 floats. Then on the next line:

ptr = arr;

You overwrite the value of ptr, causing a memory leak, with arr. This is legal because in an assignment like this an array decays into a pointer to its first element.

When you then print the values that ptr point to, you get the values in arr because that's where ptr points.

This is also why calling free on ptr is invalid since it no longer points to allocated memory.

As for the last bit of code, this is an invalid initializer:

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

When I ran this code, flag=0 showed 0 for the second and third values, while flag=1 and flag=2 showed all the expected values.

You only need one set of braces:

float arr1[3]={1.07,3.01,5.02};
like image 70
dbush Avatar answered Dec 06 '25 11:12

dbush


Solution without error

#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);
}
like image 40
Jeet Parikh Avatar answered Dec 06 '25 13:12

Jeet Parikh