Michael Schäfer
Michael Schäfer

Reputation: 175

reason for pointer to a const pointer when using static_cast

I have tried to solve an exercise from a book but I failed on the static_cast. I used the qsort Method from cstdlib. I have to cast the parameters of my function to a C-String (const char*). But I always get the error message: stattic_cast from type 'const void*' to type 'const char**' casts away qualifiers.

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);

The solution is as follows

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

What is the reason for the last const and where does it come from? Why I have to cast to a pointer to a constant pointer to char const?

Upvotes: 2

Views: 435

Answers (2)

M.M
M.M

Reputation: 141554

The qsort comparator parameters are pointers to const versions of the elements being compared. In your example the elements being compared are const char *, so a pointer to const of that is const char * const *. Hence the correct version of the code:

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
}

You can do away with pc1, pc2 and apply * operator to the result of the cast if you like .

Perhaps you mistakenly assumed the arguments were the elements being compared, when in fact they are pointers to the elements being compared .

If it is still not clear then maybe it would help to use a symbolic name for the element type:

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
}

The same pattern would work for elements that are not pointers (e.g. integer elements).

Upvotes: 2

It comes from the origin pointer. static_cast may not discard the const qualifier. So you can only cast void const* to a T const*.

Now, it just so happens that your T is a char const*. You were probably led astray by the leading const in your original code. It does not apply where one may think it applied.

Upvotes: 4

Related Questions