Search code examples
cansi-c

Why Quick sort function change argument's value


I'm reading 'The ANSI-C programming language' at Recursion part. I'm running the recursion example:

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

static int v[] = {1,3,6,1,2,3,6,89,3,5,7,2,3};
int size = sizeof(v)/sizeof(v[0]);

void sy_swap (int v[], int i, int j);
void sy_qsort(int v[], int left, int right);

/*Swap function*/
void sy_swap (int v[], int i, int j)
{
    int temp;
    temp = v[i];
    v[i] = v[j];
    v[j] = temp;
}

/*Sort function*/
void sy_qsort(int v[], int left, int right)
{
    int i, last;
    static int loop = 0;

    if(left >= right){  /*Finish sort*/
        return;
    }
    sy_swap(v, left, (left + right)/2); /*Move middle element to beginning of the half*/
    last = left;
    for(i = left+1; i<=right; i++){ /*After this loop, we have to half: smaller than 'middle element' and bigger*/
        if (v[i] < v[left]){
            sy_swap(v, ++last, i);
        }
    }
    sy_swap(v, left, last); /*Move 'middle element' to the head of SMALL half, to finish division the array into 2 half*/

    sy_qsort(v,left, last-1);   /*Sort Small Half*/
    sy_qsort(v, last+1, right); /*Sort Big Half*/

}

int main(void)
{
    int i = 0;

    printf("sizes: size of v=%d, size of v[0]=%d, total elements=%d\n",(int)sizeof(v), (int)sizeof(v[0]),size); /*Check 'size' before sort*/
    sy_qsort(v,0,size);
    printf("sizes: size of v=%d, size of v[0]=%d, total elements=%d\n",(int)sizeof(v), (int)sizeof(v[0]),size); /*Check 'size' after sort*/

    for (i =0; i<size; i++){
        printf("%d,",v[i]);
    }

    return (0);
}

Do anyone know why 'size' variable was changed after sort function was called despite there is no operation inside sort function change the 'right' argument?

This is the result show that 'size' was changed from actual 13 (total number of elements in array) to 89 (biggest element in array)

sizes: size of v=52, size of v[0]=4, total elements=13
sizes: size of v=52, size of v[0]=4, total **elements=89**
1,1,2,2,3,3,3,3,5,6,6,7,13,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0......

Solution

  • You have undefined behavior because you include the size of the array as a valid index, which it is not.

    Take for example the loop

    for(i = left+1; i<=right; i++)
    

    In the first call to sy_qsort from the main function, the variable right is equal to size which is the size of the array, but as an index it is one beyond the last element. The condition needs to be i < right.