carrayssortingpointersshellsort

Warning: assignment makes integer from pointer without a cast in shellsort algorithm


I'm writing a program to perform shellsort on an array of numbers. I first have to generate the sequence of numbers that shellsort will be performed with. This function is to generate numbers of the form 2^p*3^q that are less than the length of the array to be sorted. Then I sort the sequence array that I just generated. Here's my implementation of this:

long * Generate_2p3q_Seq(int length, int *seq_size) {
  int ind = 0;
  long * arr[1000];
  int product;
  int power = 1;
  while (power < length) {
    product = power;
    while (product < length) {
      arr[ind] = product;
      product *= 3;
      ind++;
    }
    power *= 2;
  }
  int i, j, k;
  for (i = 0; i < ind; ++i) {
    for (j = i + 1; j < ind; ++j)
    {
      if (arr[i] > arr[j])
      {
        k =  arr[i];
        arr[i] = arr[j];
        arr[j] = k;
      }
    }
  }
  *seq_size = ind;
  for (int count = 0; count < ind; count++) {
    printf("arr[%d] = %li\n", count, arr[count]);
  }
  return arr;
}

The code is meant to return a long * array and set seq_size to the length of the sequence array. For example, if I'm given an array of 16 integers to be sorted, the sequence array generated here should be 8 integers (1, 2, 3, 4, 6, 9, 8, 12) and seq_size should equal 8. I believe my understanding of pointers is wrong because my terminal output looks like this:

sequence.c: In function ‘Generate_2p3q_Seq’:
sequence.c:14:16: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
       arr[ind] = product;
                ^
sequence.c:26:11: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
         k =  arr[i];
           ^
sequence.c:28:16: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
         arr[j] = k;
                ^
sequence.c:34:25: warning: format ‘%li’ expects argument of type ‘long int’, but argument 3 has type ‘long int *’ [-Wformat=]
     printf("arr[%d] = %li\n", count, arr[count]);
                       ~~^            ~~~~~~~~~~
                       %ln
sequence.c:36:10: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
   return arr;
          ^~~
sequence.c:36:10: warning: function returns address of local variable [-Wreturn-local-addr]

However, I'm not sure how to change this to make it work. I call this function with:

  long * sequence = Generate_2p3q_Seq(size, &seq_size);

Please let me know if there's any information I've left out, I really appreciate any help.


Solution

  • There are two main issues here. First, you declare arr as long *arr[1000], which means it is an array of pointer to long, not an array of long. That is why you're getting about conversions between pointers and integers.

    The proper way to define an array of long is:

    long arr[1000];
    

    But this then leads to the second problem, namely that you are returning a pointer to a local variable. When the function returns its local variables go out of scope, so the returned pointer no longer points to valid memory.

    To fix this, declare arr as a pointer and use malloc to dynamically allocate memory for it:

    long *arr = malloc((product * power) * sizeof *arr);
    if (!arr) {
        perror("malloc failed");
        exit(1);
    }
    

    Then you can return the value of arr, which points to dynamically allocated memory.