2009-03-20 11 views
7

Mögliche Duplizieren:
Problem compiling K&R exampleZeigerart Mismatch Warnung in Beispiel von K & R C

In letzter Zeit habe ich mich durch die C-Programmiersprache von K & R. arbeitet

In Abschnitt 5.11 behandeln sie Zeiger auf Funktionen und nach der Eingabe in ihrem Beispiel - eine Quicksort-Implementierung, wo wir einen Zeiger auf den Compari bieten Sohn-Funktion, die wir verwenden möchten - Ich erhalte eine Warnung vom Compiler: Zeigertyp stimmt nicht mit Bedingungsausdruck überein. (Mein Compiler gcc 4.0.1 auf OS X 10.5.6)

Die Zeile aus dem Beispiel, das die Warnung ausgelöst wird:

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

Das Programm ohne Speicherzugriffsfehler führt, aber Ich mag jede Warnung an smoosh Ich kann oder verstehe ihre Ursachen zumindest.

Die Funktionsdeklaration für numcmp wie folgt aussieht:

int numcmp(char *, char *); 

Aber nach der Man-Page, hat stcmp diese Signatur:

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

ist die einfache Warnung wegen der etwas anderen Methode Signaturen? Was sind die Konsequenzen der Ignorierung der Warnung?

+0

Eddie zeigte auf einen Betrogenen. Ich habe gewählt, um meine eigene Frage zu schließen, aber ich dachte, dass es eine Möglichkeit geben würde, wie der Besitzer es kurzerhand schließen könnte. – Dana

+0

Dana, check out [Problem Kompilierung K & R Beispiel] (http://StackOverflow.com/Questions/616906/Problem-Compiling-Kr-Beispiel/616929) und Sie werden wahrscheinlich die Antwort auf Ihre Frage dort finden. Lass es uns wissen, wenn du es nicht tust. – Eddie

Antwort

1

Eine Möglichkeit zu versuchen und zu diagnostizieren ist zu sehen, was passiert, wenn Sie den Ausdruck mit dem?: Mit nur einem der beiden ersetzen.

Wenn es nur für strcmp und nicht numcmp passiert, dann könnte es sehr wohl wegen const char * sein. Ich denke, dass, während char * immer in void * umgewandelt werden kann, const char * nicht in void * als "sicher" umgewandelt werden kann.

Wenn es mit beiden ist, dann handelt es sich vielleicht um ein Problem mit Funktionszeigern, wo das char * in void * konvertiert werden kann, aber die Signaturen sollten identisch sein und Leerstellen anstelle von Zeichen sind ein Problem.

3

Kurze Antwort: K & R wusste C. nicht

Lange Antwort: Sie wurden durch die Tatsache behindert, dass, als sie begannen, niemand C kannten, so waren sie irgendwie so dass es sich als sie gingen mit.

(Ein wenig) weniger frivol Form der langen Antwort: Die Sprache entwickelt hat (manche würden sagen geändert) ziemlich viel, da K & R geschrieben wurde, aber es sei denn, Sie haben die E-Book-Version mit dem dynamischen Beispiel Morphing, die Beispiele in Ihrer Kopie von K & R haben nicht mit der Sprache "neu und genehmigt" ("jetzt mit noch mehr ANSI!") Schritt gehalten.

7

Obwohl Sie implizit ein char * in ein void * umwandeln können, können Sie dasselbe für einen Funktionszeiger mit diesen Typen (ohne eine Warnung) nicht tun. Der Compiler ist vorsichtiger bei der Typübereinstimmung bei Funktionssignaturen.

Ganz zu schweigen davon, dass das, was in qsort passiert, das Gegenteil ist: Das heißt, ein void * würde in ein char * in numcmp und const char * in strcmp umgewandelt werden.

Und der Compiler sollte in diesen Fällen eine Warnung ausgeben. Wenn Sie wirklich eine Funktion verwenden müssen, die nicht die gleichen Typen wie Parameter hat, sollten Sie vielleicht eine Wrapper-Funktion verwenden, die den Typen entspricht, und dann beim Aufruf der ursprünglichen Funktion die entsprechende explizite Umwandlung durchführen.

Zum Beispiel:

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

Und die modernen Signatur für qsort ist

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

Die Frage der const scheint nicht ins Spiel in Frage zu kommen, aber K & R tat nicht haben const.

+0

Eine andere Möglichkeit besteht darin, den ternären Ausdruck wie folgt zu ändern: numerisch? (int (*) (void *, void *)) numcmp: (int (*) (void *, void *)) strcmp); Also einfach die zwei verschiedenen Funktionen separat zu qsort übergeben. Dies vermeidet auch jegliche Warnungen des Compilers – bryanph