0

I have the following Counting Sort function

/*
 *File: countingSort.c
 *Description: A counting sort subroutine. Takes as input an array of integers.
 *             an array length and a range. All values in the input array must fall within                  [0, range].
 *            Takes O(range + arrayLen) time and O(range + arrayLen) extra space
 *
*/

#include "countingSort.h"

int* countingSort(int unsorted[], int arrayLen, int range) {
  int store[range + 1];
  int sorted[arrayLen];

  for ( int i = 0; i <= range; i++ ) {
    store[i] = 0;
  }

  for ( int i = 0; i < arrayLen; i++ ) {
    sorted[i] = 0;
  }

  for ( int j = 0; j < arrayLen; j++ ) {
    store[unsorted[j]] ++;
  }

  for ( int i = 1; i <= range; i++ ) {
    store[i] += store[i-1];
  }

  for( int j = arrayLen - 1; j >= 0; j-- ) {
    sorted[store[unsorted[j]]] = unsorted[j];
    store[unsorted[j]] --;
  }

  return sorted;
}

The function is giving me really strange output. The output is nothing like the input most of the times but sometimes it just works. Why is this happening?

I am calling it from another file called cSortTest.c. That file looks like this

/*
 *File: cSortTest.c
 *Description: Tests countingSort.c
 *
*/

#include <stdio.h>
#include "countingSort.h"

int main() {
  int data[8] = { 2, 1, 9, 4, 4, 56, 90, 3 };
  int* p;

  p = countingSort(data, 8, 90);
  for ( int i = 0; i < 8; i++ ) {
    printf("%d Element: %d\n", i, *(p+i) );
  }
}

1 Answer 1

3

You are returning a local array variable. This variable is destroyed when the function exits, making the address to it no longer safe or valid to access. In fact accessing it will give you what is called undefined behavior, which explains why it sometimes appears to "work".

This is a classic beginner's mistake in C. You must either have the caller pass in the desired destination array, or use malloc() to allocate "persistent" heap memory and return that:

int* countingSort(int unsorted[], int arrayLen, int range) {
  int *sorted = malloc(arrayLen * sizeof *sorted );
  if (sorted== NULL)
    return NULL;
  /* rest of sorting */
  return sorted;
}

The arrayLen * sizeof *sorted expression computes the number of bytes required for the allocation. There's no need to use calloc() which clears the memory; you're going to overwrite each element so clearing it is just wasted effort.

Sign up to request clarification or add additional context in comments.

1 Comment

Should I use alloc()/calloc() for arrays as this page seems to suggest

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.