Home > Blockchain >  Initialize an array in a loop (array vs malloc)
Initialize an array in a loop (array vs malloc)

Time:12-24

Hi I am quite new to C and I have a question about the behavior of array initialization using [] and malloc.

int main() {
    int* pointer;
    
    for(int i = 0; i < 100; i  ) {
        // Init the Array
        int tmp[2] = {}; 
        
        // Do some operation here...
        tmp[0] = 0; 
        tmp[1] = i; 
        
        // If the value is 1, copy that array pointer
        if(i == 1) {
            pointer = tmp;
        }
    }
    
    // expected 1 here, but got 99
    printf("%d\n", pointer[1]);
    
    return 0;
}

Why is the output 99? I thought the array is re-inited every loop, but it turns out using the same memory address. And if I use malloc to init the array instead, the result becomes 1 as expected.

Is there any way I could get result 1 without using malloc?

CodePudding user response:

  1. Your code is invalid as you access the variable which is out of the scope using the reference. It is undefined behaviour.

  2. Every time you assign the i to the same element to the array. Pointer only references (points to) the first element of this array. So if you change the underlaying object the value you get using the reference will change as well. If your finger is pointing to the box of 5 apples and someone eats 2 apples, your finger will point to the box of 3 apples, not 5.

You need to make a copy of the object.

        if(i == 1) {
            pointer = malloc(sizeof(tmp));
            memcpy(pointer, tmp, sizeof(tmp));
        }

or break the loop (declaring it static or moving the tmp out of the for loop scope)

    for(int i = 0; i < 100; i  ) {
        // Init the Array
        static int tmp[2]; 
        
        // Do some operation here...
        tmp[0] = 0; 
        tmp[1] = i; 
        
        // If the value is 1, copy that array pointer
        if(i == 1) {
            pointer = tmp;
            break;
        }
    }

CodePudding user response:

The scope of the array tmp is the block scope of the for loop

for(int i = 0; i < 100; i  ) {
    // Init the Array
    int tmp[2] = {}; 
    
    // Do some operation here...
    tmp[0] = 0; 
    tmp[1] = i; 
    
    // If the value is 1, copy that array pointer
    if(i == 1) {
        pointer = tmp;
    }
}

That is in each iteration of the loop a new array tmp is created and ceases to be alive after exiting the block.

Thus the pointer pointer is invalid after the for loop. Dereferencing the pointer after the for loop invokes undefined behavior.

You have gotten the result 99 only because the array tmp was not being reallocated and the memory occupied by the array was not yet overwritten. So the last value stored in this extent of memory that is the value of i equal to 99 was outputted.

Even if you will declare the array tmp before the for loop then using the pointer pointer you will get as the output the value 99 that is the value last stored in the array.

You could write for example

int tmp[2] = { 0 };
int *pointer = tmp;

for(int i = 0; i < 100; i  ) {
    // Do some operation here...
    tmp[0] = 0; 
    tmp[1] = i; 
}

And the last value stored in the array (when i is equal to 99)

    tmp[1] = i; 

will be outputted in this call

printf("%d\n", pointer[1]);

Pay attention to that such an initialization with empty braces is invalid in C opposite to C

int tmp[2] = {}; 

You need to write at least like

int tmp[2] = { 0 }; 

CodePudding user response:

As we know pointer stores a memory address. Here, I think when you give the command: pointer = tmp;, the address of the array stored in 'tmp' is copied to the 'pointer'. But when the loop of i = 1 gets completed, the array that you created in that particular loop and the pointer 'tmp' gets forgotten. Then the loop for i=2 starts, 'tmp' and the array gets created again. It happens again till the loop end.

I think that the program is storing tmp[1] at the same location every time due to which the data stored at that changes again and again. So, when you give the command printf("%d\n", pointer[1]);, the data at that address get printed which is no longer equal to 1, it has changed. The mistake is that we shared the address of 'tmp' with the 'pointer'.

But when we use malloc, we lock that memory means other programs can't use that memory. ( That's why we always need to free that memory to avoid memory leaks ). It's the reason while using malloc you get output as 1 as your other commands can't touch that particular memory.

Solution:

If you want to solve the problem without malloc. Initialise 'pointer' as an array to store data of 'tmp'. use this code, pointer[0] = tmp[0]; pointer[1] = tmp[1]; at place of pointer = tmp;.

Now, you will not be copying addresses to 'pointer' but the data in the 'tmp'. And if you have a big array with many values in it, just use it for loop. solution image

Also, you will get the same problem if you do it like this, all because of copying only the address, you will be doing the same thing. Maybe you can relate,same problem image Thanks.

  • Related