2016-01-11 3 views
0

Я изучал программирование С из книги «Практика программирования» Кернигана и Пайка. Основываясь на материале в этой книге, я написал небольшую программу для сортировки массива целых чисел, заданных в командной строке.Сравнение qsort: почему const void *?

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

#define MAXSIZE 30 

char *progname; 
int arr[MAXSIZE]; 

int icmp(int *, int *); 

int main(int argc, char *argv[]) { 
    int i; 
    progname = argv[0]; 
    if (argc == 1) { 
     fprintf(stderr, "usage: %s [int ...]\n", progname); 
     exit(1); 
    } 
    for (i = 0; argc > 1 && i < MAXSIZE; i++, argc--) { 
     arr[i] = atoi(argv[i+1]); 
    } 
    int n = i; 
    qsort(arr, n, sizeof(*arr), icmp); 
    for (i = 0; i < n; i++) { 
     printf("%d ", arr[i]); 
    } 
    printf("\n"); 
    exit(0); 
} 

int icmp(int *p1, int *p2) { 
    int v1 = *p1; 
    int v2 = *p2; 
    if (v1 < v2) { 
     return -1; 
    } else if (v1 == v2) { 
     return 0; 
    } else { 
     return 1; 
    } 
} 

Да, моя маленькая программа, похоже, работает, и я вполне доволен ею. Однако моя реализация отличается от той, которая приведена в книге, которая, похоже, не правильно сортирует целые числа. Авторы определяют icmp() как:

int icmp(const void *p1, const void *p2) { 
    int v1, v2; 
    v1 = *(int *) p1; 
    v2 = *(int *) p2; 
    if (v1 < v2) { 
     return -1; 
    } else if (v1 == v2) { 
     return 0; 
    } else { 
     return 1; 
    } 
} 

Что такое сделка? Моя версия также бросает предупреждение от НКИ:

warning: passing argument 4 of 'qsort' from incompatible pointer type 

Но, то QSort с правильным типом указателя не правильно сортировать мой Интс! Очень смутно. Если кто-нибудь сможет просветить меня, я буду очень благодарен.

+2

Передача указателя функции неправильного типа вызывает неопределенное поведение, когда qsort пытается вызвать функцию. – immibis

+2

Что значит «qsort с правильным типом указателя неправильно сортирует мои ints»? –

+0

, вы должны использовать исходный argc-1 вместо sizeof (arr *) в аргументах qsort. – softwarenewbie7331

ответ

4

сравнение qsort: почему const void *?

Если вы проверить прототип qsort, вы найдете:

void qsort (void* base, size_t num, size_t size, 
     int (*compar)(const void*,const void*)); 

Тип параметра функции compar является const void * как вы заметили.

  • Это void * потому qsort предполагается сортировать общего типа, а не только int. Вы можете отсортировать массив из double, массив string, массив struct и так далее.
  • Это const void *, чтобы избежать случайных изменений данных, на которые указывает указатель (в пределах этой функции compar). Это всего лишь типичная мера безопасности ключевого слова const.