Forum: Mikrocontroller und Digitale Elektronik Libs in .C oder .H


von Achim S. (achims)


Lesenswert?

Hallo
bin beu einem Projekt mit den Datein in .C und .H etwas durcheinander 
gekommen.
Was muss in die (Datei).C und was muss in die (Datei).H?
Es geht dabei um selbstgeschriebene Datein mit den verschiedenen Teilen 
eines Programmes. Dabei besonders um die ganzen voids. Teilweise nehmen 
diese Teile eines Programmes viel Platz ein oder um wiederkehrende Teile 
eines Programmes mehrfach zu nutzen.
achim

von Peter II (Gast)


Lesenswert?

Achim S. schrieb:
> Dabei besonders um die ganzen voids
was meinst du damit?

> Was muss in die (Datei).C und was muss in die (Datei).H?
in C sollte die Implementierung der Funktionen
in H sollte die Definition der Funktionen

von Marc (Gast)


Lesenswert?

Deklaration, nicht Definition!

von proggen (Gast)


Lesenswert?

Hallo

Was sollen voids sein? Variablen? Funktionen?

Sorry wenn ich falsch liege, aber ich glaube Du solltest Dich nochmal 
mit den Grundlagen zu C beschäftigen. Zumindest vermittelt mir Dein Post 
den Eindruck.

Zu deiner Frage was in die Headerfile soll empfehle ich dir diesen 
Artikel:
http://embeddedgurus.com/barr-code/2010/11/what-belongs-in-a-c-h-header-file/
(Die Kommentare unter dem Blogpost sind auch interessant...)

Generell kann man auf der Seite viele Ideen und Anregungen zur 
Verbesserung des eigenen Programmierstils finden ;)


Viel Erfolg!

von Achim S. (achims)


Lesenswert?

Mit void meine ich das:

void Versuch()
  {
    mach was:
  }

Ich finde es wieder sehr hilfreich von euch, wenn ihr einfach auf ein 
Fachbuch verwaist. Wenn ich die ganzen Beiträge hier oder im Netz so 
ansehe, scheint es sehr kompliziert zu sein, was was ist. Oder habe ich 
eine einfache, nicht komplizierte Erklärung überlesen?

Das sieht schon  so aus, was ich suche:

Peter II schrieb:
>> Was muss in die (Datei).C und was muss in die (Datei).H?
> in C sollte die Implementierung der Funktionen
> in H sollte die Definition der Funktionen

In (Datei).c Implementierung der Funktion
und in (Datei).h die eigentliche Definition der Funktion

achim

von Rolf M. (rmagnus)


Lesenswert?

Achim S. schrieb:
> Mit void meine ich das:
>
> void Versuch()
>   {
>     mach was:
>   }

Ah, das ist also ein "void". Eine Funktionsdefinition, die in diesem 
Fall eben den Rückgabetyp void hat...

> Das sieht schon  so aus, was ich suche:
>
> Peter II schrieb:
>>> Was muss in die (Datei).C und was muss in die (Datei).H?
>> in C sollte die Implementierung der Funktionen
>> in H sollte die Definition der Funktionen
>
> In (Datei).c Implementierung der Funktion
> und in (Datei).h die eigentliche Definition der Funktion

Die Implementierung ist die eigentliche Definition der Funktion.
In den Header gehört die Deklaration. Diese macht nur Name und Typ der 
Funktion bekannt. Ins C-File gehört dann die Implementation, also der 
eigentliche Inhalt der Funktion.

von chris_ (Gast)


Lesenswert?

>Mit void meine ich das:
>void Versuch()

Ja, das void hatte mich früher auch immer irritiert. Übersetzt heißt es 
"leer" und im Bezug auf die Funktion bedeutet es, dass die Funktionen 
nichts zurück gibt.

von c-basics (Gast)


Lesenswert?

Achim S. schrieb:
> Mit void meine ich das:
>
> void Versuch()
>   {
>     mach was:
>   }

...ja und? Frage an dich: was sind/machen den dir "void"s?

Wenn du mal eins der angesprochenen C-Bücher gelesen hättest, würdest du 
nicht eine solche Frage stellen! Qualifizierte und beantwortbare Fragen 
kann man nur dann sinnvoll stellen, wenn man die entsprechenden 
Grundlagen kennt. Deine Frage liest sich etwas verwirrt, was die 
Beantwortung nicht leichter macht!

von grundschüler (Gast)


Lesenswert?

in *.c muss rein, was selbständig kompilierbar sein soll. In *.h muss 
rein, was die main-Datei braucht, um die selbständig kompilierten 
c-Dateien zu erfassen.

von c-basics (Gast)


Lesenswert?

grundschüler schrieb:
> in *.c muss rein, was selbständig kompilierbar sein soll. In *.h muss
> rein, was die main-Datei braucht, um die selbständig kompilierten
> c-Dateien zu erfassen.

...nicht ganz: xxx.h sollte auch das enthalten, was zum (eigenständigen) 
Übersetzen von xxx.c benötigt wird.

von Falk B. (falk)


Lesenswert?


von MaWin (Gast)


Lesenswert?

und was muss in die (Datei).H?

In .c kommt der Code, also das was durch den Compiler zu ausführbarem 
Code wird, dein // mach was.

.c
1
void Versuch()
2
{
3
  // mach was
4
}
In .h kommt nur die Definition, also der Funktionsname ohne Body.

.h
1
void Versuch(void);
und damit der Compiler prüfen kann, ob beides übereinstimmt, nimmt man 
den .h in den .c durch ein #include auf

.c
1
#include "versuch.h"
2
void Versuch()
3
{
4
}

In den Programmteilen, die dann die Library versuch.lib verwenden, nimmt 
man auch die .h Datei per #include auf. Dann kann man due Funktion 
Versuch von dort aufrufen, obwohl es den Code nur in der Library gibt.

Auch ohne Library macht man das so, wenn man das Programm in 2 .c 
Dateien aufteilt. main.c enthält #include "versuch.h" und darf damit die 
Funktion Versuch() aufrufen die in versuch.c steht, wenn man beides 
zusammen kompiliert
gcc main.c versuch.c -o programm.exe

von Steffen R. (steffen_rose)


Lesenswert?

MaWin schrieb:
> void Versuch()

und

MaWin schrieb:
> void Versuch(void);

ist nicht das Gleiche!

von M. K. (sylaina)


Lesenswert?

MaWin schrieb:
> In .h kommt nur die Definition

Das heißt immer noch Deklaration.

Und noch ein Tipp:

Die .h sollte man immer so aufbauen:
1
#ifndef my_h
2
#define my_h
3
// alle relavanten deklarationen
4
#endif

Das hat den Vorteil, wird die my.h in verschiedenen Programmbereichen 
includiert, so wird sie vom Compiler nur ein einziges mal eingefügt und 
nicht mehrfach was ja das Target unnötig sonst vergrößern würde.

von Peter D. (peda)


Lesenswert?

Achim S. schrieb:
> Was muss in die (Datei).C und was muss in die (Datei).H?

Ganz einfach. Alles, was Code oder Daten erzeugt, kommt ins c-File, 
alles andere ins h-File.
Im h-File stehen also alle Deklarationen, Macros, Inline-Funktionen.
Kommentare (Funktionsbeschreibungen) sollten in beiden stehen.

Zu jedem c-File gehört ein gleichnamiges h-File, wo alles drinsteht, was 
andere Funktionen zur Nutzung des c-Files brauchen.

von chris_ (Gast)


Lesenswert?

>Ganz einfach. Alles, was Code oder Daten erzeugt, kommt ins c-File,
>alles andere ins h-File.

Sehr interessant ist aber auch die Frage:

1. wann kommen includes in include files
2. wann kommen includes ins c-files

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1 & 2: Wenn sie dort gebraucht werden.

Im übrigen hat nichts von den hier betrachteten Fragestellungen 
irgendwas mit Libraries zu tun.

Weder *.c noch *.h-Dateien sind Libraries.

von Peter D. (peda)


Lesenswert?

chris_ schrieb:
> 1. wann kommen includes in include files
> 2. wann kommen includes ins c-files

Auch ganz einfach:
Immer dann, wenn es Fehler oder Warnungen gäbe, sobald im Code kein 
anderes Include davor steht.
Z.B. eine Deklaration benutzt uint8_t, dann muß das <stdint.h> 
includiert werden.
Sauber ist es, ins c-File die gleichen Includes zu schreiben und das 
gleichnamige *.h und die *.h aller benötigten Funktionen.

von chris_ (Gast)


Lesenswert?

>Auch ganz einfach:

Hmm ... ich hätte da noch folgenden Vorschlag:
1. mit includes kann man die Interfacefunctionen von Libraries sichtbar 
machen
2. will man eine Libray includieren dann sind alle Deklarationen der 
include-Files in den Include Files für den "Includierer" sichtbar
3. Das ist nicht immer erwünscht, in diesem Fall fügt man die includes 
ins C-File

von Programmiersprachentheaterintendant (Gast)


Lesenswert?

> mit den Datein in .C und .H etwas durcheinander
> gekommen.

> um die ganzen voids.
> nehmen ... viel Platz ein

q.e.d.1: Programmieren ist komplex und erfordert abstrahierendes 
Denkvermögen UND Disziplin. (beides kann nicht Jeder gleich gut)

q.e.d.2: die Familie der C-Sprachen IST KOMPLIZIERT. Jedenfalls 
komplizierter als nötig um "Programmierung" in der Realität umzusetzen.
Die C-Familie trennt nicht sauber Low-Level von High-Level noch ist 
Modularisierung sauber umgesetzt: alles ist ein zu pragmatisches, 
organisch gewuchertes Mischmasch. Alles wird auf die Disziplin des 
Programmieres abgewälzt; von Ihm werden allzutiefe UND breite 
Vorkenntnisse vorausgesetzt inkl. das ständige vorhalten des gesamten 
Wissens darüber.

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> In .h kommt nur die Definition, also der Funktionsname ohne Body.

DEKLARATION! Ist das denn so schwierig?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peters Beitrag beschreibt die gängige Praxis am besten, so sollte man es
machen. Nur noch ein paar kleine Anmerkungen:

Peter D. schrieb:
> Ganz einfach. Alles, was Code oder Daten erzeugt, kommt ins c-File,

Exakt. Von dieser Regel gibt es auch kaum Ausnahmen, so dass sich ein
Programmieranfänger immer daran halten sollte. Das "was Code oder Daten
erzeugt" ist im C-Standard genau festgelegt und nennt sich dort
"external definition".

> alles andere ins h-File.

Nicht unbedingt. Deklarationen, die nur in einer einzigen
Überstzungseinheit genutzt werden, dürfen gerne auch in deren .c-Datei
stehen. Wenn solche lokalen Deklarationen aus Übersichtsgründen in eine
.h-Datei ausgelagert werden, sollten sie nicht mit Deklarationen
vermischt werden, die in mehreren Übersetzungseinheiten genutzt werden.

> Im h-File stehen also alle Deklarationen, Macros, Inline-Funktionen.

Ersetze "alle" durch "ausschließlich", dann stimmt's.

> Zu jedem c-File gehört ein gleichnamiges h-File, wo alles drinsteht, was
> andere Funktionen zur Nutzung des c-Files brauchen.

Wenn es nichts gibt, was von anderen Übersetzungseinheiten benutzt wird,
kann man sich die .h-Datei schenken. Das betrifft aber normalerweise
nur diejenige .c-Datei, die die main()-Funktion enthält.

Wenn mehrere Übersetzungseinheiten zu einer Bibliothek zusammengefasst
werden, kann man (muss aber nicht) auch die .h-Dateien zusammenzufassen,
um deren Anzahl etwas zu verringern.

von Ben S. (theben)


Lesenswert?

Es gibt verschiedene Arten wie man eine .h Datei verwenden kann.

Dieses einfache Deklarationen in die .h und Implementationen in die .c 
finde ich nicht immer günstig.

In Programmen mit vielen .c und .h Dateien kann es da schnell zu 
Doppelbenamungen kommen. Für mich kommen nur die Deklarationen in die .h 
rein, die auch außerhalb der .c Datei bekannt sein sollen. zB.:

ich habe die Funktionen dateiauslesen() und kleine_hilfsfunktion() in 
einer dateifunktionen.c da würde bei mir die die Deklaration der 
dateiauslesen() in die dateifunktionen.h kommen und die Deklaration der 
kleine_hilfsfunktion(), sowie die Implementationen der beiden Funktionen 
in die dateifunktionen.c Datei.

Eine Weitere sinvolle Verwendung von .h Dateien ist die übersichtliche 
Sammlung von #define Einträgen. zB. für ein Programm das eine Temperatur 
überwachen soll. Die verschiedenen Temperatur-Grenzwerte könnten dann 
gesammelt in einer Temperatur.h stehen. In dieser Datei steht dann aber 
nichts anderes mehr drin (außer Kommentare natürlich). Somit ist ein 
größeres Programm sehr übersichtlich und Parameter können schnell 
gefunden und angepasst werden

von Rolf M. (rmagnus)


Lesenswert?

Yalu X. schrieb:
>> Im h-File stehen also alle Deklarationen, Macros, Inline-Funktionen.
>
> Ersetze "alle" durch "ausschließlich", dann stimmt's.

Nein, denn da müssen z.B. auch Typdefinitionen stehen.

von my2ct (Gast)


Lesenswert?

chris_ schrieb:
> Ja, das void hatte mich früher auch immer irritiert. Übersetzt heißt es
> "leer" und im Bezug auf die Funktion bedeutet es, dass die Funktionen
> nichts zurück gibt.

Was dazu im Wörterbuch als Bedeutung steht, ist ziemlich belanglos. In C 
handelt sich um einen Datentyp.

Eine Variable des Datentyps void hat die Länge 0 mit einer Leeren Menge 
als Wertebereich.

von error: variable has incomplete type 'void' (Gast)


Lesenswert?

my2ct schrieb:
> Eine Variable des Datentyps void hat die Länge 0 mit einer Leeren Menge
> als Wertebereich.

Mit welchem Compiler kann man denn eine Variable vom Typ void 
deklarieren?

von Rolf M. (rmagnus)


Lesenswert?

error: variable has incomplete type 'void' schrieb:
> my2ct schrieb:
>> Eine Variable des Datentyps void hat die Länge 0 mit einer Leeren Menge
>> als Wertebereich.
>
> Mit welchem Compiler kann man denn eine Variable vom Typ void
> deklarieren?

Variablen vom Typ void kann man nicht anlegen, da void per Defintion ein 
unvollständiger Typ ist. Eine Größe hat void damit in dem Sinne einfach 
nicht, genausowenig wie einen Wertebereich.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Achim S. schrieb:
> Mit void meine ich das:
>
> void Versuch()
>   {
>     mach was:
>   }

Oh, dann ist das so etwas wie ein 710er-Deckel! Kannst Du uns im 
Gegenzug vielleicht erklären, wozu solch ein Deckel gut ist?

http://www.rainereisenhuth.de/710erdeckel.jpg

von Peter D. (peda)


Lesenswert?

void hat nur seinen Platz in Funktionsdeklarationen als Argument bzw. 
Returntyp.
Dirty (void*) casts sollte man möglichst vermeiden.

Deklaration: Funktion/Variable bekannt machen
Definition: Funktion/Variable mit Inhalt füllen

Formalismen helfen vorrangig Dir, dem Programmierer, auch wenn das ein 
Anfänger ungern einsehen will.
Daß Du dann weniger Fehler machst bzw. Fehler schneller findest, ist 
pure Absicht.
Daß ein anderer Deinen Code besser lesen kann oder weniger meckert, ist 
nur ein kleiner Nebeneffekt.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Rolf M. schrieb:
> Yalu X. schrieb:
>>> Im h-File stehen also alle Deklarationen, Macros, Inline-Funktionen.
>>
>> Ersetze "alle" durch "ausschließlich", dann stimmt's.
>
> Nein, denn da müssen z.B. auch Typdefinitionen stehen.

Ich wollte das in meinem obigen Beitrag erst ebenfalls anmerken, habe es
dann aber gelassen, da auch Typdefinitionen Deklarationen sind. Dass das
so ist erkennt man daran, dass sie im C-Standard auch im Abschnitt
"Deklarations" abgehandelt werden.

von Dirk B. (dirkb2)


Lesenswert?

c-basics schrieb:
> grundschüler schrieb:
>> in *.c muss rein, was selbständig kompilierbar sein soll. In *.h muss
>> rein, was die main-Datei braucht, um die selbständig kompilierten
>> c-Dateien zu erfassen.
>
> ...nicht ganz: xxx.h sollte auch das enthalten, was zum (eigenständigen)
> Übersetzen von xxx.c benötigt wird.

Nein.

In xxx.h kommen nur die Schnittstelleninformationen rein.

Interne Funktionen und Informationen bleiben in xxx.c

von Rolf M. (rmagnus)


Lesenswert?

Andreas S. schrieb:
> Oh, dann ist das so etwas wie ein 710er-Deckel!

Hier kann man den auch kaufen ;-)
http://etel-tuning.eu/exterieur/171-der-710-er.html

Yalu X. schrieb:
> Ich wollte das in meinem obigen Beitrag erst ebenfalls anmerken, habe es
> dann aber gelassen, da auch Typdefinitionen Deklarationen sind. Dass das
> so ist erkennt man daran, dass sie im C-Standard auch im Abschnitt
> "Deklarations" abgehandelt werden.

Nach der Logik würden dann aber auch die Funktions-Definitionen dorthin 
gehören, denn die sind ja auch gleichzeitig Deklarationen.
Eine Definition ist aber nicht "ausschließlich" eine Deklaration.

Um's nochmal zusammenzufassen:

Funktionen werden in Headern nur deklariert. Globale Variablen 
ebenfalls. Typen müssen dagegen - sofern sie von verschiedenen c-Files 
aus nutzbar sein sollen, im Header definiert werden, nicht nur 
deklariert.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Rolf M. schrieb:
> Typen müssen dagegen - sofern sie von verschiedenen c-Files aus nutzbar
> sein sollen, im Header definiert werden, nicht nur deklariert

Ausser man nutzt nur einen Pointer auf den Datentyp, und dereferenziert 
diesen nicht. So kann man auch unvolständige typen nutzen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Rolf M. schrieb:
> Yalu X. schrieb:
>> Ich wollte das in meinem obigen Beitrag erst ebenfalls anmerken, habe es
>> dann aber gelassen, da auch Typdefinitionen Deklarationen sind. Dass das
>> so ist erkennt man daran, dass sie im C-Standard auch im Abschnitt
>> "Deklarations" abgehandelt werden.
>
> Nach der Logik würden dann aber auch die Funktions-Definitionen dorthin
> gehören, denn die sind ja auch gleichzeitig Deklarationen.
> Eine Definition ist aber nicht "ausschließlich" eine Deklaration.

Es ist müßig, über die Begriffe und deren Auslegung diskutieren, denn
die Regel kann letztendlich ganz einfach formuliert werden:

------------------------------------------------------------------------
Alles, was im C-Standard im Abschnitt "External definitions"¹ aufgeführt
ist, gehört in eine .c-Datei.
------------------------------------------------------------------------

Diese Regel sagt implizit auch aus, dass alles andere wahlweise in einer
.c- oder .h-Datei stehen darf. In welche .c- oder .h-Datei man nun die
Dinge, die keine external Definitions sind, genau schreibt, das ist
wieder ein anderes Thema und leider nicht durch eine ähnlich einfache
Regel zu erschlagen.

————————————
¹) Das sind Funktionsdefinitionen, die nicht inline sind, und externe
   Objektdefinitionen.

: Bearbeitet durch Moderator
von Rolf M. (rmagnus)


Lesenswert?

Daniel A. schrieb:
> Rolf M. schrieb:
>> Typen müssen dagegen - sofern sie von verschiedenen c-Files aus nutzbar
>> sein sollen, im Header definiert werden, nicht nur deklariert
>
> Ausser man nutzt nur einen Pointer auf den Datentyp, und dereferenziert
> diesen nicht. So kann man auch unvolständige typen nutzen.

Gut, das hängt von der Definition von "nutzen" ab. Für mich ist es noch 
nicht Nutzung eines Datentyps, wenn ich einen Zeiger darauf von irgendwo 
bekomme und irgendwo anders wieder abgebe.

Yalu X. schrieb:
> Es ist müßig, über die Begriffe und deren Auslegung diskutieren, denn
> die Regel kann letztendlich ganz einfach formuliert werden:
>
> -----------------------------------------------------------------------
> Alles, was im C-Standard im Abschnitt "External definitions" aufgeführt
> ist, gehört in eine .c-Datei.
> -----------------------------------------------------------------------

Ob es nun einfacher ist, aus dem C-Standard zu entnehmen, was "external 
definitions" sind oder eher ein paar mehr Regeln zu haben, sei mal 
dahingestellt.

> Diese Regel sagt implizit auch aus, dass alles andere wahlweise in einer
> .c- oder .h-Datei stehen darf. In welche .c- oder .h-Datei man nun die
> Dinge, die keine external Definitions sind, genau schreibt, das ist
> wieder ein anderes Thema und leider nicht durch eine ähnlich einfache
> Regel zu erschlagen.

Eine einfache Regel wäre, in das Interface, also den Header so wenig wie 
möglich, aber so viel wie nötig reinzustecken. Was man von außen nicht 
braucht, muss auch nicht im Header stehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.