2016-05-03 3 views
0

Я попытался сортировать свою среду.Сортировка среды Unix в C

Моя версия C++ (строка std :: sort вместе со классом CstrLess) работает, но версия qsort терпит неудачу. Что я делаю не так?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <algorithm> 
extern char** environ; 


struct CstrLess{ 
    bool operator()(const char* s1, const char* s2){ return ::strcmp(s1,s2)<0; } 
}; 

int main(){ 
    char** env = environ; 
    size_t sz = 0; 
    for(;*env; env++,sz++) {;} //measure the env 

    //? 
    qsort(environ, sz, sizeof(char*), (int (*)(const void*, const void*)) strcmp); 

    /*std::sort(environ, environ + sz, CstrLess{});*/ 

    env = environ; 
    while(*env){ 
    printf("%s%c", *env++, '\0'); 
    } 

    return 0; 
} 
+0

Что вы имеете в виду под «не может»? – ecatmur

+0

'qsort' pass' char ** 'на' strcmp', а не 'char *'. – BLUEPIXY

+0

@ecatmur Выход не сортируется. – PSkocik

ответ

2

qsort передает свою функцию сравнения указатели к элементам, чтобы быть по сравнению; вам необходимо непрямое, что указатель, чтобы получить char const* указатели должны быть переданы strcmp:

qsort(environ, sz, sizeof(char*), 
    [](const void* a, const void* b) { 
     return strcmp(
      *reinterpret_cast<const char**>(a), *reinterpret_cast<const char**>(b)); }); 

Чистое решение C:

int qsort_strcmp(const void* a, const void* b) { 
    return strcmp(*(const char**)(a), *(const char**)(b)); 
} 

// ... 

    qsort(environ, sz, sizeof(char*), qsort_strcmp); 
+0

Это помечено C. – Lundin

+0

@ Lundin исправлено, спасибо. – ecatmur

+0

Почему приведение к 'const char **' btw? Кажется совершенно излишним. – Lundin

1

Указатель strcmp имеет тип int(*)(const char *, const char *).

Тип, ожидаемый qsort, является int(*)(const void*, const void*).

Преобразования указателей на Wild-функции - это неопределенное поведение. Ваш компилятор по праву дал бы вам предупреждение/ошибку, если бы вы не заставили его замолчать с уродливым броском. Возможно, что для разных типов могут быть разные соглашения о вызовах, поэтому это неопределенное поведение является серьезной проблемой.

Правильный подход заключается в написании функции обертку и передать указатель на что вместо:

int strcmp_wrapper (const void* s1, const void* s2) 
{ 
    return strcmp(s1, s2); // implicit conversion from const void* to const char*. 
} 
Смежные вопросы