причина указателя на константный указатель при использовании static_cast - PullRequest
2 голосов
/ 26 сентября 2019

Я пытался выполнить упражнение из книги, но мне не удалось выполнить static_cast.Я использовал метод qsort из cstdlib.Я должен привести параметры моей функции к C-String (const char *).Но я всегда получаю сообщение об ошибке: stattic_cast от типа 'const void *' к типу 'const char **' отбрасывает квалификаторы.

int scmp(const void *s1, const void *s2) {
    const char *c1 = (static_cast<const char**>(s1));
    const char *c2 = (static_cast<const char**>(s2));
    ....
}

const char *sfield[] = {"one", "two", "three", "four", "five"};
qsort(sfield, 10, 4, scmp);

Решение состоит в следующем

const char *c1 = *(static_cast<const char* const*>(s1));

В чем причина последнего const и откуда он?Почему я должен привести к указателю на константу указатель на char const?

Ответы [ 2 ]

3 голосов
/ 26 сентября 2019

Это исходит из указателя источника.static_cast не может сбрасывать квалификатор const.Таким образом, вы можете разыграть void const* до T const*.

Теперь, так уж вышло, что ваш T является char const*.Вы, вероятно, были сбиты с толку ведущими const в вашем исходном коде.Он не применяется там, где это может показаться.

1 голос
/ 26 сентября 2019

Параметры компаратора qsort являются указателями на постоянные версии сравниваемых элементов.В вашем примере сравниваемые элементы const char *, поэтому указатель на const равен const char * const *.Следовательно, правильная версия кода:

int scmp(const void *s1, const void *s2) 
{
    auto pc1 = static_cast<const char * const *>(s1);
    auto pc2 = static_cast<const char * const *>(s2);

    char const *c1 = *pc1;
    char const *c2 = *pc2;

    return strcmp(c1, c2);  // or whatever
}

Вы можете покончить с pc1, pc2 и применить оператор * к результату приведения, если хотите.

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

Если все еще неясно, возможно, будет полезно использовать символическое имя для элементатип:

using ELEMENT_T = const char *;

int scmp(void const *s1, void const *s2) 
{
    auto pc1 = static_cast<ELEMENT_T const *>(s1);
    auto pc2 = static_cast<ELEMENT_T const *>(s2);

    ELEMENT_T c1 = *pc1;
    ELEMENT_T c2 = *pc2;

    return strcmp(c1, c2);  // or whatever
}

Тот же шаблон будет работать для элементов, которые не являются указателями (например, целочисленные элементы).

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