externe funktionen



  • moin

    gegeben sei mal folgendes beispiel:

    /* main.c */
    #include "misc.h"
    
    int main(void)
    {
      int i,j;
      i = foo();
      j = anderer_int;
      printf("%i %i\n",i,j);
      return 0;
    }
    
    /* misc.h */
    #include <stdio.h>
    extern int anderer_int;
    extern int foo(void);  
    
    /* misc.c */
    #include "misc.c"
    
    int anderer_int = 255;
    
    int foo(void)
    {
      return 2;
    }
    

    bau das ganze mit:
    gcc -c misc.c
    gcc -c main.c
    gcc -o app main.c misc.c
    zusammen..

    funktioniert alles so wie ich mir das vorstelle, aber..
    dabei scheint es egal zu sein ob ich "extern int foo(void)" in dem header
    file deklariere oder nicht.. fuer main.c ist foo() doch eine externe funktion!?
    immerhin muss ich den anderern_int auch also extern deklarieren sonst ist
    er in main.c nicht bekannt..
    die funktion scheint also nicht in dem header file stehen zu muessen?!.. ich finde sowas aber öfter mal in anderen source codes.. aber wozu is das gut?

    gruß stahl



  • Anhand des header-files und des darin enthaltenen Prototypen Deiner Funktion erkennt der Compiler, wie die entsprechende Funktion aufgerufen werden muss. Er kann dann eine Typprüfung der Parameter und der Rückgabewertes durchführen.

    Wenn Du einmal den Prototypen weglässt, dann kannst Du die Funktion auch mit Parametern aufrufen. Eine Zeile wie etwa

    i = foo("Hallo", "Welt");
    

    wird dann nicht als Fehler erkannt. In C89 (und in K&R-C) wird, wenn kein Prototyp vorhanden ist, ausserdem implizit "int" als Returnwert angenommen.



  • wenn du nicht willst, dass du auf die Funktion foo Zugreifen kannst, dann musst du das static Keyword benutzen



  • interessant. danke euch beiden.



  • @kingruedi: Der Specifier 'static' schränkt nur den Sichtbarkeitsbereich einer Funktion ein (beschränkt auf die aktuelle Datei). Deswegen kann man aber immernoch aus einer anderen C-Source darauf zugreifen ...

    /* foo1.c */
    
    void *get_fct(void);
    
    int main(void)
    {
        void *f = get_fct();
    
        (*(int(*)(void))f)();
    
        return 0;
    }
    
    /* foo2.c */
    
    #include <stdio.h>
    
    static int foo(void)
    {
        return printf("bin in foo()\n");
    }
    
    void *get_fct(void)
    {
        return foo;
    }
    

    Ist aber ein bisschen weit hergeholt, das Beispiel ... :))



  • Original erstellt von mady:
    @kingruedi: Der Specifier 'static' schränkt nur den Sichtbarkeitsbereich einer Funktion ein (beschränkt auf die aktuelle Datei).

    Tun wir i Puenktchen reiten?

    Jede Funktion oder Variable muss irgendwo (im Speicher) stehen - da kann man natuerlich mit fiesen Tricks immer darauf zugreifen...



  • Wenn ich mich nicht täusche haben die anderen deine Frage garnicht beantwortet 🙂

    Also extern sagt nichts anderes aus als daß sich die Funktion oder Variable die du als extern deklarierst nicht in dem Modul (die .o-Datei) befindet.
    Es ist daher auch völlig sinnlos sie in misc .h als extern zu deklarieren, denn sie befinden sich ja im Modul misc.
    Sinnvoll wird es erst dann wenn du dein Beispiel folgendermassen umänderst:

    /* main.c */
    extern  int foo();
    extern  int anderer_int;
    
    int main(void)
    {
    
      int i,j;
      i = foo();
      j = anderer_int;
      anderer_int = 22; // bewirkt Änderung in misc.c
      printf("%i %i\n",i,j);
      return 0;
    } 
    
    /* misc.h */
    #include <stdio.h>
    int anderer_int;
    int foo(void);  
    
    /* misc.c */
    #include "misc.h" 
    int anderer_int = 255; int foo(void)
    {
      return 2;
    }
    

    Das kompilierst du mit
    gcc -o main main.c misc.c

    Du kannst also ohne die Header-Datei zu benutzen auf Funktionen oder Variablen im Modul misc zugreifen.
    Sinnvoll wird es wenn du Variablen in einem anderem Modul ändern willst, also von main aus die Variable anderer_int ändern.

    Noch was zu static. static macht nichts anderes als Variablen einmal zu initialisieren.

    Beispiel:

    void increment()
    {
      static int x=1000;
      x++;
    }
    

    Es passiert folgendes: Beim ersten Aufruf wird x mit 1000 initialisiert.
    Bei den nächsten mal wird x durch die Zuweisung nicht mehr beeinflußt
    static int x=1000; wird also ignoriert.

    [ Dieser Beitrag wurde am 11.10.2002 um 18:22 Uhr von agrimm editiert. ]

    [ Dieser Beitrag wurde am 11.10.2002 um 18:28 Uhr von agrimm editiert. ]



  • nabend

    also für sinnlos halte ich das nicht, btw. hätte ich misc.h auch beliebig anders nennen können. so wie ich das gemacht habe muß ich nicht in jemdem c-file alle externen variablen und funktionen die ich verwenden möchte aufführen, hier reicht dann ein einzelnes #include "misc.h".

    du machst das genau anders rum. zudem kann man in dem umgeändertem beispiel misc.h
    auch gleich weglassen.

    [ Dieser Beitrag wurde am 11.10.2002 um 19:05 Uhr von stahl editiert. ]



  • Mir ist noch was aufgefallen.
    Wie du dein Programm kompilierst ist doch zuviel des guten.
    gcc -c misc.c // sinnlos weil schon im letzten Befehl
    gcc -c main.c // sinnlos weil schon im letzten Befehl
    gcc -o app main.c misc.c

    so wär's sinnvoll
    gcc -c misc.c // erzeugt misc.o
    gcc -c main.c // erzeugt main.o
    gcc -o app main.o misc.o

    🙂



  • hallo stahl,
    na klar kannst du das auch so machen, aber:
    die in main deklarierten externen variablen kannst du in main nach belieben ändern. wenn du in main also anderer_int änderst, bekommen alle funktionen in
    misc diese änderung mit. das ist auf normale weise nicht möglich. die variable wird sozusagen global.



  • ja, hallo agrimm

    das is doch gehüpft wie gesprungen.. in beiden varianten laesst sich doch dasselbe mit den externen variablen anstellen.. ob ich nun

    /* main.c */
    extern int foo;
    
    int main(void)
    {
      // mach boese dinge mit foo
      return 0;
    }
    

    habe, oder ..

    /* xyz.h */
    extern int foo;
    /* main.c */
    #include "xyz.h"
    
    int main(void)
    { 
      // mach boese dinge mit foo
      return 0;
    }
    

    letzteres wird dann sinnvoll, wenn ich mehrere c-files diese externen varibalen/funktionen verwenden sollen.



  • Dein Beispiel:

    /* main.c */
    extern int foo; // irgendwo in meinem Projekt gibt es foo
    
    int main(void)
    {
      // mach boese dinge mit foo
      return 0;
    }
    

    Ob du Zeile 1 nun mit #include reinholst oder direkt reinschreibst (nichts anderes macht der Präprozessor) ist ziemlich egal. Beide Beispiele machen dasselbe, da hast du recht.Du musst aber wissen das du in
    Zeile 1 keine Variable erzeugst. Du sagst dem Compiler doch nur, daß in irgendeinem Modul die Variable foo vorkommt, die du gerne ändern möchtest (oder gerne Zugriff hättest).
    Klingelt's



  • dessen bin ich mir bewußt, siehe mein erstes beispiel.

    [ Dieser Beitrag wurde am 11.10.2002 um 20:00 Uhr von stahl editiert. ]



  • Dann weißt du doch worum es geht. Warum die Frage? In deinem allerersten Beispiel sagst du doch main.c (weil du misc.h "included" hast) das foo() extern ist. Bei Funktionen (!) ist das ziemlich egal, denn jede Funktion ist, soweit nicht anders deklariert extern, denn das ist die Standardeinstellung. Bei Variablen nicht, hast du auch gemerkt!
    Ich glaube aber nicht, das wenn du keinen Prototyp deklariert hast, es durch den Compiler geht.
    Es sei denn:
    Ohne Prototyp musst du die Funktion als extern in main.c deklarieren. Dann geht's durch und du brauchst die header-Datei nicht.
    Wenn du es in anderen Quellcodes gesehen hast, beziehen sich diese extern-Funktionen meisst auf Bibliotheken oder object-files, für die kein Quellcode vorhanden ist. Das Wort extern kann man sich dabei aber sparen, das ist gimmick wenn die header-files da sind.

    PS: habe deine frage recht unaufmerksam gelesen, sorry, ich dachte du wolltest wissen wozu extern da ist.



  • denn jede Funktion ist, soweit nicht anders deklariert extern

    ja, das war mir aber nicht klar als ich das thema begann. ich hab aber wie gesagt in anderen source immer wieder sowas gesehen, wo funktionen ausdrücklich als extern in den headern deklariert wurden, und das waren auch programm interne funktionen..
    ...und ich wollte wissen wozu 'extern' in diesen speziellen fällen gut ist, bzw was es bewirkt, und dazu hat mady mir ja was erzählt.

    so ich hoffe wir haben das jetzt geklärt



  • wir reden nicht von static Variablen, sondern von static Funktionen, static bei Funktionen hat eine andere Auswirkung, als bei lokalen Variablen!



  • hm halt. es reicht doch auch ein normaler prototyp der funktion, warum dem ganzen noch ein extern verpassen? hmhm...



  • Eben, überflüssig!


Anmelden zum Antworten