www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Funktionen auslagern


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Wie lagere ich denn Funktionen in Header-Dateien aus?
Muss ich die Prototypendeklaration in der Header mit den Funktionen
oder im Hauptfile angeben?

Gruß
Markus

Autor: TOM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Markus,

ich habe es immer folgendermasen gemacht.
Ein seperates Headerfile erstellen.
Deine Funktion z.B. "int xxx (int z,int y)" schreibst Du auch in
dieses Headerfile "extern int xxx (int,int);" somit ist diese
bekannte nun bindest Du dieses Headerfile in Deinem main Programm mit
#include <HEADERFILE.h> ein.
Nun solltest Du Deine Funktion aus main aufrufen können.

TOM

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Tom!
Muss ich im Main den Prototyp auch noch einmal deklarieren oder reicht
das im Header?
Wie mache ich es mit den Variablen und/oder LookUpTables die ich für
das Unterprogramm verwende?
Sie werden auch im Hauptprogramm verwendet.

Autor: Karl heinz Buchegger (heinzi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Prototypen deklarierst Du im Headerfile. Und dieses
Headerfile #include -st Du dann dort wo dus brauchst, zb. im main().

Das Grundprinzip ist doch folgendes in C:

Jedes Source Code file wird fuer sich alleine vom Compiler
uebersetzt. Und in jeder dieser Source Code Einheit muss alles
deklariert sein, was der Compiler nicht von sich aus kennt.
Natuerlich kannst Du auch komplett auf den Header pfeifen und
in jedem Source Code die Dinge einzeln deklarieren. Etwa so:

File1.c
******

int foo( int bar );

void foo2()
{
  int j = foo( 5 );
}

File2.c
*******

int foo( int bar );

void foo3()
{
  int k = foo( 7 );
}

Main.c
******

int foo( int bar );
void foo2( void );
void foo3( void );

int main()
{
  int l = foo( 8 );
  foo2();
  foo3();
}

aber Du merkst schon, wo das hinfuehrt:
Wenn Du foo() anederst, zb indem ein zusatzlicher Parameter mit
aufgenommen wird, so musst Du die Aenderung in diesem Fall an
4 Stellen machen:
 1) foo selbst
 2) den Prototypen in File1.c
 3) den Prototypen in File2.c
 4) den Prototypen in Main.c

Das das bei vielen Funktionen und vielen Files mehr als
fehleranfaellig
ist, brauchen wir wohl nicht zu diskutieren.

Dazu gibt es aber in C den Mechanismus des #include

Bevor sich der Compiler den eigentlichen Programtext vornimmt, rauscht
der erstmal durch den Praeprozessor. Der ersetzt alle Zeilen mit
  #include <Dateiname>
durch den aktuellen Inhalt der Datei namens 'Dateiname'.

Du schreibst also zb.

Foo.h
*****

int foo( int bar );

File1.c
*******

#include "Foo.h"

void foo2()
{
  int j = foo( 5 );
}

File2.c
*******

#include "Foo.h"

void foo3()
{
  int k = foo( 7 );
}

Uebersetzt du zb. File1.c, dann passiert Folgendes:
Zuerst nimmt sich der Praeprozessor den Text vor und ersetzt
die Zeile
  #include "Foo.h"
mit dem Inhalt der Datei 'Foo.h'.
Als Ergebnis erhaelt er:

int foo( int Bar );

void foo2()
{
  int j = foo( 5 );
}

und erst dieses Ergebnis wird durch den tatsaechlichen C Compiler
gejagt. Der ist natuerlich happy damit, denn in der Funktion foo2()
wird eine andere Funktion foo() benutzt und deren Protoyp wurde
ja korrekt angegeben.

Aber: Aendert sich an der Funktion foo() etwas, dann aenderst Du
einfach nur an einer einzigen Stelle den Protoypen: in Foo.h
alle anderen, File1.c File2.c und Main.c  kriegen das automatisch
mit, da sie ja Foo.h inkludieren und somit die Aenderung beim
Compilieren mitkriegen.

Variablen/Lookup Tabellen.
Im Prinzip machst Du genau das gleiche, nur kommt Dir hier die
ODR (One Definition Rule) in die Quere. Jedes Teil darf nur einmal
definiert werden!
Bei einem Protoypen weiss der Compiler auch so, dass es sich um einen
Prototypen handelt. Etwas in der Form

  int foo( int bar );

kann nur ein Protoyp (also eine Deklaration) sein. Eine Definition
wuerde ganz anders aussehen

  int foo( int bar )
  {
    /* Implementierung von foo */
  }

bei globalen Variablen ist das aber anders. Ist

  int Global1;

nun eine Definition oder eine Deklaration.
Antwort: Es ist eine Definition.
Wenn Du sowas in Foo.h stehen haettest, dann wuerde der Compiler
klarerweise beim Uebersetzen von File1.c eine Variable namens
Global1 anlegen. Dasselbe wuerde er aber auch machen, wenn File2.c
und Main.c uebersetzt werden. Das geht aber nicht, denn dann wuerde
der Linker 3 Variablen namens Global1 sehen und nicht wissen, welche
denn dir Richtige ist.
Also muss man das anders machen: Die Definition muss zu einer
Deklaration werden:

Foo1.h
******

int foo( int bar );
extern int Global1;

Damit wissen alle *.c Bescheid, dass es irgendwo eine Variable namens
Global1 gibt und das diese vom Typ int ist.
Soweit so gut. Aber irgendwo muss diese Variable auch tatsaechlich
existieren, sonst koennte der Linker sie nicht finden.
Na zb. hier:

Main.c
******

#include "Foo.h"

int Global1;   /* da ist sie. Die Variable 'Global1'
                  Alle anderen die Foo.h inkludieren wissen nur
                  dass es sie gibt. Aber hier ist sie tatsaechlich */

int main()
{
  Global1 = 5;
}

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Respekt, das ist doch mal ne Antwort!

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Heinzi
Supergenial! Vielen Dank!

Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Echt ne richtig schöne ausführliche Antwort, da hatte wohl schon jemand
einen zuviel getrunken und konnte sich aufgrund des Alkoholgehaltes im
Blute wohl nicht mehr zusammenreißen und musste alles schreiben was er
zu diesem Thema wusste und dann auch noch so, dass man es ohne große
Kenntnisse verstehen kann :).
Es sollte an jedem Tag Karnevalanfang sein, dann würde es hier bestimmt
öfters solche schönen ausführlichen Antworten geben...einfach klasse :)

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau mal in die Codesammlung. Dort gibt es einige Beiträge von Peter
Dannegger. In diesen sind meist Zip-Dateien zu finden, die komplette
Projekte enthalten. Dort kann der C-Interessierte sehen, wie man
strukturierte Programme schreibt. Dort sieht man auch, was in den
Header gehört und was in die Programmdatei. Mir persönlich ist das zwar
etwas zu hoch (ich kann kein C), aber wer C auf AVR oder 51er lernen
will, der kann sich da 'ne Menge abschaun. Ist jedenfalls besser, als
hier herumzuattern und nix zu verstehen.

Gruß und Bit- & Bytebruch...
...HanneS...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.