Search code examples
cinitialization

C : If as I understand 0 and '\0' are the same, how does the compiler knows the size of an array when I write int my_array = {0};?


I am trying to create a function to copy an array into another using pointers. I'd like to add the following condition : if the array of destination is smaller, the loop must break.

So basically it's working, but it is not working if I intilize the the destination array as follows :

int dest_array[10] = {0};

From what I understand it fills the array with int 0's which are equivalent to '\0' (null characters). So here is my question :

In this case how can the computer know the array size or when it ends ?

(And how do I compare arrays passed as parameters ?)

void copy(int *src_arr, int *dest_arr)
{
    // The advantage of using pointers is that you don't need to provide the source array's size

        // I can't use sizeof to compare the sizes of the arrays because it does not work on parameters.
        // It returns the size of the pointer to the array and not of of the whole array

    int* ptr1;
    int* ptr2;

    for(     ptr1 = source, ptr2 = dest_arr ;
        *ptr1 != '\0'              ;        
             ptr1++, ptr2++            )
    {   
        if(!*ptr2) // Problem here if dest_arr full of 0's
                { 
                     printf("Copy interrupted :\n" +
                            "Destination array is too small"); 
                     break; 
                }

        *ptr2 = *ptr1;
    }

Solution

  • TL/DR - You will need to pass the array size as a separate parameter to your function. Sentinel values like 0 only mark the logical end of a sequence, not the end of the array itself.

    Unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. So when you pass your source and destination arrays as arguments to copy, what the function actually receives is just two pointers.

    There's no metadata associated with a pointer that tells it whether it's pointing to the first object in a sequence, or how long that sequence is1. A sentinel value like the 0 terminator in strings only tells you how long a logical sequence of values is, not the size of the array in which they are stored2.

    You will need to supply at least one more parameter to copy to tell it how large the target buffer is, so you stop copying when you've reached the end of the target buffer or you see a 0 in the source buffer, whichever comes first.


    1. The same is true for array objects - there's no runtime metadata in the array object to store the size or anything else. The only reason the sizeof trick works is that the array's declaration is in scope. The array object itself doesn't know how big it is.
    2. This is a problem for library functions like strcpy, which only receives the starting address for each buffer - if there are more characters in the source buffer than the target is sized to hold, strcpy will blast right past the end of the target buffer and overwrite whatever follows.