2

I'm currently working my way through the K&R exercises, and there's something that's bugging me.

I have the qsort function declaration:

void qsort(void *v[], int left, int right,
           int (*comp)(void *, void *));

According to the book, I should be able to use the conditional expression to choose the compare function. I've got two of those:

int numcmp(char *s1, char *s2)

and the cstring's

int strcmp(const char *s1, const char *s2);

The call looks like:

qsort((void **)lineptr, 0, nlines - 1,
            (int(*)(void *, void *))(numeric ? numcmp : strcmp));

And my MS VS gives me an error:

Error: operand types are incompatible

Yet, when I do it like:

qsort((void **)lineptr, 0, nlines - 1,
            (numeric ? (int(*)(void *, void *))numcmp : (int(*)(void *, void *))strcmp));

all is OK.

Is the book wrong, or is it just VS's idea of how it should be done?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Bart
  • 420
  • 3
  • 18
  • 2
    What is surprising there? The conditional operator cannot accept 2 arguments when neither can be implicitly converted to the others type, but you can naturally cast them to the same type yourself beforehand. – Deduplicator Mar 01 '15 at 16:35
  • possible duplicate of [Ternary operator](http://stackoverflow.com/questions/4693629/ternary-operator) – edmz Mar 01 '15 at 16:36
  • I'm not using the stdlib's qsort. The declaration is from a function written by the authors. The definition is also there. What is surprising is that the authors used the 1st way in the book. And I'm wondering if the code from the book is simply old enough to not be accepted by VS, or am I doing something wrong here. – Bart Mar 01 '15 at 16:37
  • Note that if you are converting the function pointer you pass to `qsort`, you are using it wrong. http://c-faq.com/lib/qsort2.html – Pascal Cuoq Mar 01 '15 at 17:11

2 Answers2

4

In the description of the conditional operator in C Standard (6.5.15 Conditional operator) there is written:

3 One of the following shall hold for the second and third operands: — both operands are pointers to qualified or unqualified versions of compatible types;

Compatible functions shall have compatible parameters.

As your functions have pointers as parameters then

2 For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.

However the parameters of the two functions are not identically qualified.

Thus the compiler is correct.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thank you, that's it. Suddenly it became very clear. The authors must've meant the `strcmp` that is indeed defined earlier in the book, and takes two `char*` arguments. In this case there would be no error. – Bart Mar 01 '15 at 16:50
  • The `const` qualifier didn't exist when K&R published "The C Programming Language". If it were updated to modern C, both of those functions would be made const-correct by adding the const modifier to their parameters. – Theodore Murdock Jul 13 '17 at 19:06
1

Your error is using a bad prototype for your custom comparison-function numcmp.
It should take pointers to const:

int numcmp(char const *s1, const char *s2); // Showing both equivalent orders for const

The conditional operator cannot accept arguments 2 and 3 where neither can be implicitly converted to the others type, but you can naturally cast them to the same type yourself beforehand.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118