arrayscfor-loopsizeoffunction-definition

Junk when printing C array


I've implented a program in the C programming language to reverse an array of ints (As an exercise)

#include <stdio.h>

#define procedure void

procedure reverse_arr(int A[], size_t N)
{
    for(int i = 0; i < N / 2; i++){
        A[i] = A[i] ^ A[N-1-i];
        A[N-1-i] = A[N-1-i] ^ A[i]; 
        A[i] = A[i] ^ A[N-1-i];
    }
}

procedure print_array(int A[], size_t N)
{
    for(int i = 0; i < N; i++)
        printf("%d\n", A[i]);
}

int main()
{
    int A[5] = {1, 2, 3, 4 ,5};
    print_array(A, sizeof(A));
    reverse_arr(A, sizeof(A));
    print_array(A, sizeof(A));
}

I've tested it and it gives me the following results:

1 2 3 4 5 0 -13168 0 -13088 0 -2147180803 1 -2139062144 -2139062144 -2147180911 1 -13168 0 6 0 0 6 0 -13168 1 -2147180911 -2139062144 -2139062144 1 -2147180803 0 -13088 0 -13168 0 5 4 3 2 1

As you can see, at the start it prints the original array, and at the end it prints the reversed one, but why is it printing the junk in between? there doesn't seem to be a problem with the array size and as far as i know size of 1 dimensional arrays is not needed to be known at compile time when passing it as a function parameter.

I'm compiling on windows x64 with minGW GCC.


Solution

  • The expression sizeof(A) yields the size of the whole array that is calculated like 5 * sizeof( int ) and if the sizeof( int ) is equal to 4 then the value returned by the expression sizeof( A ) will be equal to 20.

    To determine the number of elements in the array you need to use the expression

    sizeof( A ) / sizeof( *A )
    

    Though it would be simpler to define a named constant for the number of elements in the array like

    int A[] = {1, 2, 3, 4 ,5};
    const size_t N = sizeof( A ) / sizeof( *A );
    
    print_array( A, N);
    reverse_arr( A, N);
    print_array( A, N );
    

    Pay attention to that it is a bad idea to use upper case letters to name identifiers. Usually upper case letters are used to name macros or constants.

    Also introducing such a macro alias like

    #define procedure void
    

    only confuses readers of the code.

    And as the function print_array does not change the passed array then its first parameter should have the qualifier const.

    Also the second parameter of the function has the type size_t while within the function in the for loop you are using an index of the type int.

    The function should be declared and defined the following way

    void print_array( const int a[], size_t n )
    {
        for ( size_t i = 0; i < n; i++ )
            printf("%d ", a[i]);
    }
    

    After calling the function you should print the new line character

    putchar( '\n' );
    

    Otherwise all output will be in the same line.

    And instead of using the operator ^ to swap integers it is much better to use the general approach when an intermediate variable is introduced. This makes the code more readable. Make the life of readers of your code easier.:)

    The function reverse_arr can be declared and defined the following way

    void reverse_arr( int a[], size_t n )
    {
        for ( size_t i = 0; i < n / 2; i++ )
        {
            int tmp = a[i];
            a[i] = a[n - i - 1];
            a[n - i - 1] = tmp;  
        }
    }
    

    Thus your program can look the following way

    #include <stdio.h>
    
    void reverse_arr( int a[], size_t n )
    {
        for ( size_t i = 0; i < n / 2; i++ )
        {
            int tmp = a[i];
            a[i] = a[n - i - 1];
            a[n - i - 1] = tmp;  
        }
    }
    
    void print_array( const int a[], size_t n )
    {
        for ( size_t i = 0; i < n; i++ )
            printf( "%d ", a[i] );
    }
    
    int main( void )
    {
        int a[] = { 1, 2, 3, 4 ,5 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        print_array( a, N );
        putchar( '\n' );
    
        reverse_arr( a, N );
    
        print_array( a, N );
        putchar( '\n' );
    }
    

    The program output is

    1 2 3 4 5 
    5 4 3 2 1