1

So, I have some C code for a bitonic sort, and I am trying to convert that code into C#. One of the lines in the C code is confusing me. I have never worked with C before.

        void merge_up(int *arr, int n) {
      int step=n/2,i,j,k,temp;
      while (step > 0) {
        for (i=0; i < n; i+=step*2) {
          for (j=i,k=0;k < step;j++,k++) {
        if (arr[j] > arr[j+step]) {
          // swap
          temp = arr[j];
          arr[j]=arr[j+step];
          arr[j+step]=temp;
        }
          }
        }
        step /= 2;
      }
    }

    void merge_down(int *arr, int n) {
      int step=n/2,i,j,k,temp;
      while (step > 0) {
        for (i=0; i < n; i+=step*2) {
          for (j=i,k=0;k < step;j++,k++) {
        if (arr[j] < arr[j+step]) {
          // swap
          temp = arr[j];
          arr[j]=arr[j+step];
          arr[j+step]=temp;
        }
          }
        }
        step /= 2;
      }
    }

    void printArray(int *arr, int n) {
      int i;

      printf("[%d",arr[0]);
      for (i=1; i < n;i++) {
        printf(",%d",arr[i]);
      }
      printf("]\n");
    }

    int main(int argc, char **argv) {
      int n, *arr, i,s;
      FILE *fp = fopen(argv[1],"r");

      if (fp == NULL) {
        fprintf(stderr,"file not found\n");
        exit(1);
      }
      // first line gives number of numbers to be sorted 
      fscanf(fp,"%d",&n);
      // allocate space and read all the numbers 
      arr = (int *)malloc(n*sizeof(int));
      for (i=0; i < n; i++) {
        fscanf(fp,"%d",(arr+i));
      }
      // print array before 
      printArray(arr,n);

      // do merges
      for (s=2; s <= n; s*=2) {
        for (i=0; i < n;) {
          merge_up((arr+i),s);
          merge_down((arr+i+s),s); //Having trouble with this line here.
          i += s*2;
        }
      }

      printArray(arr,n);
    }

What is it doing when it calls merge_down((arr+i+s), s);

Specifically, the arr+i+s. arr is the array, but what is +i+s doing? I would really appreciate some help.

-EDIT: I should add what ive done in C# for that part. This is what ive got:

 //Do merges
        for (int s = 2; 2 <= n; s = s * 2)
        {
            for(int i = 0; i < n;){
                mergeUp(arr, s);
                mergeDown(arr, s);
                i += s * 2;
            }
        }
  • 1
    I'm sure this is a duplicate. arr is a pointer to a location in memory, and in C, arrays are stored contiguously. arr+i+s is also a pointer to a location, and the + operator magically computes the location based on the type of the array. It is essentially a subarray starting at the (i+s)th element. – UncleO Mar 11 '13 at 02:15
  • `arr+i+s` is equivalent to `&arr[i+s]` – Jim Balter Mar 11 '13 at 02:20

2 Answers2

4

Pointer arithmetic. arr is a pointer to the beginning of the array, so it's basically just the same as creating a pointer to arr[i+s].

Pointer arithmetic is not supported in C# (except in unsafe code). To convert this code to C# you'd have to create a new array to pass into mergeDown or alter the signature of mergeDown to take a startIndex parameter. Alternatively, you can make mergeDown accept a IEnumerable<T> or ArraySegment<T> and use @JimBalter's answer.

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • "it's basically just the same" -- in fact `arr+i+s` is *exactly* the same as `&arr[i+s]` – Jim Balter Mar 11 '13 at 02:22
  • "Technically, it's not exactly the same, since there is some subtlety that has to be considered with the size of each array element" -- this is incorrect; *both forms* take into account `sizeof(*arr)`. – Jim Balter Mar 11 '13 at 02:29
  • 1
    "Pointer arithmetic is supported in C#" -- It is only supported in unsafe code, which most certainly is not needed here and should not be recommended. "To convert this code to C# you'd have to create a new array to pass into merge_down" -- No, only a new IEnumerable. A new array would fail because it's modified in place. – Jim Balter Mar 11 '13 at 02:31
  • @JimBalter Thanks. I haven't done C in so long, I'd forgotten a bit. I'll update my answer. – p.s.w.g Mar 11 '13 at 02:33
1

I should add what ive done in C# for that part. This is what ive got:

   ...
   mergeUp(arr, s);
   mergeDown(arr, s);

What you want is

   mergeUp(arr.Take(i), s);

   mergeDown(arr.Take(i+s), s);

Or perhaps better use ArraySegment<T>. See Array slices in C#

Community
  • 1
  • 1
Jim Balter
  • 16,163
  • 3
  • 43
  • 66