Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer type mismatch warning in example from K&R C [duplicate]

Possible Duplicate:
Problem compiling K&R example

Lately I have been working my way through the C Programming Language by K&R.

In section 5.11 they cover pointers to functions and after typing in their example -- a quicksort implementation where we provide a pointer to the comparison function we want to use -- I'm getting a warning from the compiler: pointer type mismatch in conditional expression. (My compiler is gcc 4.0.1 on OS X 10.5.6)

The line from the example that triggers the warning is:

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

The program executes without segfaulting, but I like to smoosh every warning I can, or at least understand their causes.

The function declaration for numcmp looks like:

 int numcmp(char *, char *);

But according to the manpage, stcmp has this signature:

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

Is the warning simple because of the slightly different method signatures? What are the consequences of ignoring the warning?

like image 914
Dana Avatar asked Mar 20 '09 04:03

Dana


3 Answers

Although you can implicitly cast a char* to a void*, you can't do the same for a function pointer with those types (without a warning). The compiler is more careful with type matching on function signatures.

Not to mention that what's happening inside qsort would be the opposite: that is, a void* would be cast to a char* in numcmp and const char* in strcmp.

And the compiler should issue a warning in these cases. If you really have to use a function that doesn't have the same types as parameters, perhaps you should use a wrapper function that does match the types, and then does the appropriate explicit cast when calling the original function.

For instance:

static int strcmp_wrapper(void* s1, void* s2) {
  return strcmp((char*)s1, (char*)s2);
}

static int numcmp_wrapper(void* n1, void* n2) {
  return numcmp((char*)n1, (char*)n2);
}

qsort((void **) lineptr, 0, nlines-1,
      (numeric ? numcmp_wrapper : strcmp_wrapper));

And the modern signature for qsort is

void
qsort(void *base, size_t nel, size_t width,
      int (*compar)(const void *, const void *));

The issue of const doesn't seem to come into play in your question, but K&R did not have const.

like image 150
Jared Oberhaus Avatar answered Sep 29 '22 21:09

Jared Oberhaus


Short answer: K&R didn't know C.

Long answer: They were handicapped by the fact that when they started, no one knew C, so they were sort of making it up as they went along.

(Slightly) less flippant form of the long answer: The language has evolved (some would say changed) quite a bit since K&R was written, but unless you got the e-book version with the dynamic example morphing, the examples in your copy of K&R won't have kept up with the "new and approved" ("now with even more ANSI!") language.

like image 23
MarkusQ Avatar answered Sep 29 '22 23:09

MarkusQ


One way to try and diagnose it is to see what happens if you replace the expression with the ?: with just one of the two.

If it only happens for strcmp and not numcmp, then it could very well be because of the const char*. I think that while char* can always be converted to void*, you can't convert const char* to void* as "safely".

If it is with both, then perhaps this is about some issue with function pointers, where having the char* converted to void* works, but the signatures should be identical and having voids instead of chars are a problem.

like image 27
Uri Avatar answered Sep 29 '22 22:09

Uri