Можете ли вы логическое меньше, чем сравнить 2 пустых * значения в C? - PullRequest
1 голос
/ 11 августа 2011

Я qsort () добавляю некоторые указатели памяти в список, чтобы позже их можно было найти в функции.Мой вопрос заключается в том, нужно ли печатать приведение этих значений к чему-то другому, кроме const void *, чтобы выполнить законное сравнение в C?Я мог бы просто выполнить преобразование и позволить компилятору сообщить мне, но у меня есть ощущение, что это может зависеть от компилятора.

Ответы [ 2 ]

5 голосов
/ 11 августа 2011

Сравнения в порядке, арифметика и разыменование - нет (потому что вы не знаете размер базовых данных). Так что да, вы можете сравнить void указатели довольно хорошо (a) .

Однако имейте в виду, что обычно вы не сравниваете указатели, переданные функции сравнения qsort, если вы не хотите сортировать их адреса. Но, поскольку они уже будут отсортированы в указанном порядке (будучи массивом), для этого нет особого варианта использования: -)

Обычно вы приводите указатели void к определенному указателю, а затем сравниваете то, на что они указывают . Что-то вроде:

int compfn (const void *p1, const void *p2) {
    const char *str1 = *((const char **)(p1));
    const char *str2 = *((const char **)(p2));
    return strcmp (str1, str2);
}

Вам не нужно создавать временные файлы, такие как str1 и str2 (даже если любой приличный компилятор все равно их оптимизирует). Кроме небольшой проблемы с читабельностью, в этом нет ничего плохого:

int compfn (const void *p1, const void *p2) {
    return strcmp (*((const char **)(p1)), *((const char **)(p2)));
}

(a) В соответствии с обычными правилами, указатели должны оба указывать на элементы одного и того же массива или одного элемента за этим массивом - все остальное не определено. Я упоминаю это для полноты, но, если вы используете qsort, вы все равно будете работать с массивом.

0 голосов
/ 11 августа 2011

Обычно вы хотите сделать что-то подобное в вашей функции сравнения

int compare(const void *a, const void *b) 
{
    int aa = *(int *)a;
    int bb = *(int *)b;
    return aa - bb;
}

и преобразовать пустоту * в соответствующий тип (с int это просто пример).

ЭтоДопустимо сравнивать с типами const void *, но это сравнение адреса.Если это то, что вам нужно, то это нормально, если не применимо вышеизложенное (надуманный пример) (в зависимости от того, что вы сравниваете).

РЕДАКТИРОВАТЬ: Для вашего случая

int compare(const void *a, const void *b)
{
    if (a < b) return -1;
    else if (a == b) return 0;
    return 1;
}

ПричинаЯ делаю это так, потому что адреса имеют размер size (long без знака), который больше размера int, что может вызвать проблему, если вы переполните int каким-либо образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...