*Markus: kurze C-Frage zu strstr

Hallo,

Ich tüftle schon ziemlich lange an dem Korrigieren einer Warnmeldung herum, die mich darauf hinweist, dass eine "Unverträgliche implizite Deklaration der eingebauten Funktion strstr" stattgefunden hat, wobei es sich auf die Zeile mit "strstr" bezieht. Weiß jemand, was damit gemeint ist? Danke schon mal im Voraus.

  
    while ( !feof(fp) )    {  
        fgets(puffer, PUFFERSIZE, fp);  
        if (strstr(puffer, "RDEPEND"))   {  
           printf("%s\n", puffer);  
        }  
    }  
  

Markus

--
http://www.apostrophitis.at
六 7東曲 人港ラ
  1. hi,

    Ich tüftle schon ziemlich lange an dem Korrigieren einer Warnmeldung herum, die mich darauf hinweist, dass eine "Unverträgliche implizite Deklaration der eingebauten Funktion strstr" stattgefunden hat, wobei es sich auf die Zeile mit "strstr" bezieht. Weiß jemand, was damit gemeint ist?

    Kurzes googlen nach dem Meldungstext lässt mich vermuten, dass du einfach vergessen hast, die Bibliothek, die diese Funktion bereitstellt, explizit einzubinden.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo,

      Kurzes googlen nach dem Meldungstext lässt mich vermuten, dass du einfach vergessen hast, die Bibliothek, die diese Funktion bereitstellt, explizit einzubinden.

      Nein, da das Programm funktioniert. Die Warnung kommt aber trotzdem.

      Markus

      --
      http://www.apostrophitis.at
      六 7東曲 人港ラ
      1. Hi,

        Kurzes googlen nach dem Meldungstext lässt mich vermuten, dass du einfach vergessen hast, die Bibliothek, die diese Funktion bereitstellt, explizit einzubinden.

        Nein,

        Doch.

        da das Programm funktioniert.

        Das kommt daher, daß irgendein anderes Modul dafür sorgt, daß die entsprechende Bibliothek vom Linker berücksichtigt wird.

        Die Warnung kommt aber trotzdem.

        Die wird auch solange kommen, bis Du die Bibliothek explizit einbindest (#include ...)

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        Schreinerei Waechter
        O o ostern ...
        Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
  2. Hallo Markus,

    Ich tüftle schon ziemlich lange an dem Korrigieren einer Warnmeldung herum, die mich darauf hinweist, dass eine "Unverträgliche implizite Deklaration der eingebauten Funktion strstr" stattgefunden hat, wobei es sich auf die Zeile mit "strstr" bezieht. Weiß jemand, was damit gemeint ist?

    In C sollen Funktionen eigentlich deklariert sein, bevor man sie benutzt. Das heißt, wenn Du eine Funktion tolle_funktion() verwenden willst, muss diese vorher deklariert werden (d.h. der Prototyp der Funktion soll angegeben werden), z.B. so:

    char *tolle_funktion (int a, int b);

    Alternativ reicht es auch aus, die Funktion einfach *vorher im Code* komplett anzugeben:

    char *tolle_funktion (int a, int b) {  
        // Ja, ich weiß, sehr sinnvoll ist dieses Beispiel nicht ;-)  
        return "Hallo";  
    }
    

    Allerdings wird es in C im Allgemeinen so gehandhabt, dass man für alle Funktionen, die noch in anderen Dateien verwendet werden sollen, die Prototypen in Header-Dateien schreibt, d.h. in diesem Fall würde man folgendes machen:

    tolle_funktion.h:

    // Durch diese Anweisungen kann die Header-Datei nur einmal  
    // eingebunden werden  
    #ifndef TOLLE_FUNKTION_H  
    #define TOLLE_FUNKTION_H  
      
    char *tolle_funktion (int a, int b);  
      
    #endif
    

    tolle_funktion.c:

    #include "tolle_funktion.h"  
      
    char *tolle_funktion (int a, int b) {  
        return "Hallo";  
    }
    

    Um jetzt die Funktion nutzen zu können, musst Du in einem anderen Teil des Programms 2 Dinge tun: Zum einen solltest Du die Header-Datei einbinden, zum anderen musst Du dem Linker mitteilen, dass er tolle_funktion auch mit einbinden soll.

    Diese zwei Dinge sind völlig unabhängig voneinander. Die Header-Datei einbinden machst Du in der .c-Datei, in der Du tolle_funktion verwenden willst, über #include "tolle_funktion.h" - und schwupp, der Compiler weiß dann, wie die Funktion tolle_funktion() aussieht (Datentypen etc.). Damit Du aus der erstellen Objektdatei dann jedoch ein lauffähiges Programm machen kannst, musst Du die Objektdatei auch gegen die Objektdatei, die aus tolle_funktion.c erstellt wurde, linken, denn sonst sagt Dir der Linker "oh, Du willst tolle_funktion() in Deiner Objektdatei nutzen, ich kenne die aber nicht, kann die Referenz also nicht auflösen".

    Was passiert nun in Deinem Fall von strstr()? Ganz einfach: Du hast die notwendige Header-Datei *nicht* eingebunden, d.h. der Compiler hat keine Ahnung, was er mit strstr() anfangen soll. Da Compiler meistens nette Programme sind, sieht er darüber hinweg und erfindet sich für die Funktion eine eigene Deklaration. Dabei ist der Rückgabetyp einer solchen Funktion immer int und die Parameter werden in Abhängigkeit der übergebenen Parameter interpoliert. Hier in Deinem Fall ist das kein Problem, da NULL konvertiert zu Integer einfach 0 ergibt, weswegen die if-Bedingung trotzdem noch funktioniert. Ferner sind auf den meisten Systemen heutzutage der int-Datentyp genauso groß wie der Zeiger-Datentyp, weswegen die Konvertierung problemlos funktioniert - das muss aber nicht der Fall sein und kann deswegen zu unerwarteten Ergebnissen führen (Beispiel: int-Datentyp ist 32bit groß, Zeiger-Datentyp ist 64bit groß; Zeiger-Datentyp enthält einen Zeiger auf einen Speicherbereich, bei dem die niederwertigen 32 Bits 0 sind (z.B. 0x100000000), der jedoch nicht 0 ist; da die if-Bedingung, da sie denkt, dass der Rückgabewert int ist, nur die niederwertigen 32 Bits prüft, denkt sie, dass NULL zurückgegeben wurde, false ergibt, was dazu führt, dass der Code in so einem (zugegebenermaßen unwahrscheinlichen) Fall nicht mehr richtig funktionert). Ferner kann es möglich sein, dass die Interpolation der Parameter nicht richtig funktioniert, z.B. wenn eine Funktion einen char-Parameter (typischerweise 8 bit) erwartet und Du eine int-Variable übergibst (die würde im Normalfall halt implizit konvertiert werden) - dann kann Dir das den ganzen Stack verhunzen, da der Compiler die Parameter in falscher Größe auf den Stack legt - die Funktion könnte beim Auslesen des Stacks komplett durcheinander kommen. Deswegen sollten dem Compiler durchaus alle Funktionsprototypen schon während der Compile-Zeit bekannt sein, damit es nicht zu bösen Überraschungen kommt.

    Dann zur Quizfrage: Warum meckert der Linker nicht "unbekanntes Symbol strstr()"? Ganz einfach - strstr() ist eine Funktion der C-Standard-API, die im Normalfall *immer* vom Linker automatisch eingebunden wird (man kann es ihm aber über einen Parameter abgewöhnen) - d.h. das Symbol kann korrekt aufgelöst werden, der Linker meckert nicht.

    Was musst Du nun tun, um die Warnung zu beheben? Die korrekte Header-Datei einbinden, die den Prototypen der Funktion strstr() enthält. Der ANSI-C-Standard schreibt vor, dass die Standardfunktion strstr() in der Datei string.h deklariert wird, d.h. Du solltest in Deinen .c-Datei, in der diese Warnung auftritt, ganz oben noch ein

    #include <string.h>

    einfügen. Dann bist Du die Warnung los und - viel wichtiger - der Compiler kennt die korrekten Datentypen für die Funktion und kann daher korrekten Code erzeugen.

    Viele Grüße,
    Christian

    --
    "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup