2015-01-31 4 views
1

Приведенный ниже код получается странным при попытке сортировать серию беззнаковых длинных int. Понятия не имею почему. Он компилируется без предупреждения. Проблема заключается где-то в моем использовании qsort, но я зачищал эту линию в течение нескольких часов. Я думаю, что моя функция сравнения в порядке. Я пробовал полуслепую, пытаясь все перестановки, о которых я могу думать, чтобы удостовериться, что я передаю правильные аргументы и до сих пор не играю в кости. Любая помощь размещения мой вопрос будет иметь в виду:qsort not sorting list unsigned long ints

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

#define LENGTH 10 

static int cmpfunc (const void *a, const void *b) { 
    const unsigned long int x=*(const unsigned long int*)a, y=*(const unsigned long int*)b; 
    printf("x=%lu ",x); printf("y=%lu ",y); 
    if (x==y) { 
     puts("returning 0..."); return 0; 
    } else { 
     if (x>y) { 
      puts("returning 1..."); return 1; 
     } else { 
      puts("returning -1..."); return -1; 
     } 
    } 
} 

int main(void) { 
    /* declare the storage for our "array". Using malloc instead of [] because in 
     real program array size shall be dynamic */ 
    unsigned long int *mystorage=malloc(LENGTH*sizeof(unsigned long int)); /* check for NULL */ 

    /* fill up array with values in non-monotonic order and show the values */ 
    for(unsigned long int counter=0;counter<LENGTH;counter++) { 
     *(mystorage+counter*sizeof(unsigned long int))=(unsigned long int)(counter*(LENGTH-counter)); 
     printf("value is %lu\n",*(mystorage+counter*sizeof(unsigned long int))); 
    } 

    /* sort array */ 
    qsort(mystorage, LENGTH, sizeof(unsigned long int), cmpfunc); 

    /* print out array again to see if it changed */ 
    for(unsigned long int counter=0;counter<LENGTH;counter++) { 
     printf("value is %lu\n",*(mystorage+counter*sizeof(unsigned long int))); 
    } 

    exit(EXIT_SUCCESS); 
} 
+5

Почему вы используете эту причудливую (и неправильную) арифметику указателя вместо простой индексации массива? –

+0

используйте 'sizeof * mystorage', чтобы сделать ваш код более читаемым (и менее хрупким) (в тех местах, где' sizeof' верно, конечно) –

+0

@Oliver Charlesworth. Потому что я забыл, как правильно использовать арифметику указателя. Если вы видите эту проблему, подумайте о том, чтобы написать ответ, подобный приведенному ниже, вместо того, чтобы задавать верный вопрос. Таким образом, если вы наиболее верны в ответе, у меня есть возможность выбрать ваш ответ. –

ответ

3
*(mystorage+counter*sizeof(unsigned long int)) 
    = 
     (unsigned long int)(counter*(LENGTH-counter)); 

... неверен. (Я переставить немного ваш пробел.) Это должно быть

mystorage[counter] = 
     counter*(LENGTH-counter); // the cast is redundant 

Следующие три эквивалентны:

mystorage[counter] 
counter[mystorage]  // yes, this weird thing is equivalent 
*(mystorage+counter) 

Сравните последнюю строку кода. Когда вы добавляете указатель и целое число, компилятор уже знает, чтобы двигаться по правильному количеству байтов. Потому что вы включаете SIZEOF материал, у вас есть эти две эквивалентных линии (которые отличаются от указанных выше трех линий)

*(mystorage + counter*sizeof(unsigned long int)) 
mystorage[counter*sizeof(unsigned long int)] 

Должно быть ясно, что эти два будет иметь доступ за пределы массива.

+0

Согласен, @MattMcNabb, я изменил его –

+1

Вы правы. Прошло некоторое время с тех пор, как я написал в C, и я забыл некоторые базовые понятия C, которые в качестве арифметики указателя увеличиваются по размерам типа указателя, а не непосредственно в байтах. Теперь я чувствую себя красноватым, но благодарю вас за ваше время и ответ. –

0

Ваша программа неправильно в части

for(unsigned long int counter=0;counter<LENGTH;counter++) { 
    *(mystorage+counter*sizeof(unsigned long int))=(unsigned long int)(counter*(LENGTH-counter)); 
    printf("value is %lu\n",*(mystorage+counter*sizeof(unsigned long int))); 
} 

При добавлении некоторых целых чисел к указателю компилятор автоматически использовать адресную арифметику, так что вы не должны использовать *sizeof(unsigned long int). Такая же ошибка в контуре печати. Поэтому используйте простую индексацию mystorage[counter] или *(mystorage+counter)

Смежные вопросы