Verständnisfrage Header/include WinAVR

Gast #924143
Lesenswert?

Hallo,

ich hab eine Frage zur Verwendung von #include bzw. Header-Dateien. 
Etwas googlen und suchen in den Forumsbeiträgen brachte mich zur 
folgenden (etwas vereinfachten) allgemeinen Form:
1
/* header.h */
2
void function_1(void);  // Prototyp von function_1
3
void function_2(void);  // Prototyp von function_2
4
// usw.
5

6

7
/* header.c */
8
#include "header.h"  
9

10
void function_1(void)
11
  {
12
  // mach irgendwas..
13
  }
14

15
void function_2(void)
16
  {
17
  // mach irgendwas anderes..
18
  }
19

20

21
/* main.c */
22
#include <...>       // Standard-Bibliotheken einbinden
23
#include "header.h"  // <-- hier setzt meine Frage an (siehe unten)
24

25
void main(void)
26
  {
27
  // Hauptprogramm..
28
  }

Meine Frage ist nun, warum wird im Hauptprogramm die *.h-Datei 
eingebunden und nicht die *.c-Datei?

Ok, aus der *.h kennt der Compiler erstmal die Prototypen. Ok, soweit so 
gut. Aber woher kennt er dann die genaue Implementierung der Funktionen 
(heisste das so?)? Wird einfach davon ausgegangen, dann *.h und *.c den 
selben Namen haben?

Logischer für mich würde es irgendwie klingen, wenn ich im Hauptprogramm 
die *.C einbinde. Die Datei wiederum bindet dann die *.h ein und die 
Welt ist in Ordnung :-)

Sehe ich das richtig, dass ich auch einfach einige Funktionen in eine 
*.c auslagern kann und dann mit include "xyz.c" einbinden kann, ohne 
Header zu benutzen? (für nicht garzu allgemein nutzbare Funktionen vor 
allem).

Gruß und schonmal Danke für Erleuchtung :-)
Christian
Gast #924152
Lesenswert?

Zuallererst werden die include-Files im C-File eingefügt und auch alle 
weiteren Preprocessor-Anweisungen durchgeführt, (alle Zeilen die mit "#" 
beginnen) wie z.B. Macros substituieren.

Der Compiler übersetzt dann vorest jedes C-File einzeln zu einem 
Object-File => *.o File. Anhand der Prototypen-Deklarationen nimmt er 
an, dass die Funktion irgendwo in einem anderen Objectfile existiern 
wird,fall sie nicht schon im selben C-File vorkommt und setzt die 
entsprechenden Labels für den Linker.

Erst der Linker fügt dann alle Object-Files zu einem Programm zusammen.

Durch das Makfile weiss der Compiler+Linker welche Dateien zusammen 
gehören bzw aus welchen Source-Dateien das Programmm zusammengebaut 
werden soll.
Gast #924169
Lesenswert?

Es können *.c UND *.h Dateien eigebunden werden. Ob man *.c Dateien 
einbindet ist eigendlich nur eine Frage vom Programmierstil. Ob. die 
Funktionsdeklaration in einer *.h Datei steht hängt davon ab, ob man mit 
mehreren Dateien arbeitet und diese auf die Deklarierten Funkionen 
zugreifen müssen. In deinem Beispiel ist eine *.h Datei nicht notwendig. 
Ich persönlich halte es so, dass es in meinen Projekten nur eine Datei 
MAIN.c OHNE MAIN.h gibt. In MAIN erfolgt dann nur die Initialisierung 
und der Aufruf des Schedulers.
Gast #924340
Lesenswert?

>Es können *.c UND *.h Dateien eigebunden werden.

Können kann man alles einbinden, aber wenn überhaupt, gibt es nur ganz 
wenige Spezialfälle, wo das einbinden von .c-Dateien sinnvoll ist. 
Normalerweise braucht man das nicht.

Das funktioniert so, wie Peter es schon beschrieben hat.

Oliver
Gast #924478
Lesenswert?

Woher weiss der Compiler aber, dass die Datei Header.c mit übersetzt 
werden muss? Die wird ja nirgends mittels #include oder so erwähnt.

(Meine Funktionen hab ich nun erstmal alle mittels #include "zeugs.c" in 
eine andere Datei verlagert. So ists erstmal nicht garzu unübersichtlich 
in der Hauptdatei. Um die Funktionen ordentlich in nem anderen Projekt 
wiederverwenden zu können, müsste ich aber wohl einiges noch ein 
bisschen allgemeiner Formulieren und einige Überprüfungen einbauen.)

Bitte mich weiter erleuchten :-) :-)

Gruß und Danke
Christian
Persönliche Seite #924481
Lesenswert?

Gast123 wrote:
> Woher weiss der Compiler aber, dass die Datei Header.c mit übersetzt
> werden muss? Die wird ja nirgends mittels #include oder so erwähnt.
Durch das MAKEFILE. Oder auch dadurch, dass du alle C-Dateien der IDE 
hinzufügst, mit der du programmierst.

> (Meine Funktionen hab ich nun erstmal alle mittels #include "zeugs.c" in
Sowas macht man nicht, auch wenn es (erstmal) funktioniert ;)
Gast #924484
Lesenswert?

Der Compiler weiss es nicht. Er muss für jede Datei einzeln aufgerufen 
werden. Erst der Linker erstellt daraus (wie bereits oben geschrieben) 
"eine" fertige Programmdatei.

Damit man nicht jede Datei einzeln kompilieren und anschließend den 
Linker (vereinfacht ausgedrückt: den Zusammensetzer) aufrufen muss, gibt 
es die sogenannten Make-Dateien. Das ist soetwas wie eine Skriptdatei 
die vorher definierte Abläufe durchführt. In dieser Make-Datei muss jede 
*.c Datei eingetragen werden so dass sie vom Compiler nach und nach 
übersetzt wird. Jede c-Datei für wird für sich und ohne Wissen der 
anderen Objektdateien übersetzt. Damit nun Aufrufe aus anderen *.c 
Dateien nicht zu fehlern führen geht der Compiler davon aus, dass alle 
Funktionen die in Headerdateien definiert sind, beim linken mit in das 
endgültige Programmpaket eingefügt werden.

Steffen.
Gast #924527
Lesenswert?

1
...
2
# Output format. (can be srec, ihex, binary)
3
FORMAT = ihex
4

5

6
# Target file name (without extension).
7
TARGET = main
8

9

10
# List C source files here. (C dependencies are automatically generated.)
11
SRC = $(TARGET).c     # <--- HIER?
12

13

14
# List Assembler source files here.
15
#     Make them always end in a capital .S.  Files ending in a lowercase .s
16
#     will not be considered source files but generated files (assembler
17
#     output from the compiler), and will be deleted upon "make clean"!
18
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
19
#     it will preserve the spelling of the filenames, and gcc itself does
20
#     care about how the name is spelled on its command-line.
21
ASRC = 
22
...

Aaaaah, langsam beginne ich zu verstehen :-) :-) Also könnte ich in dem 
obigen Schnipsel aus dem makefile meine Datei zeugs.c eintragen (und 
nicht per #include im Hauptprogramm). Die Datei würde dann separat 
übersetzt werden. Dann würde aber wohl der Compiler beim hauptprogramm 
meckern, weil er die Funktionen nicht kennt. Das wiederum würde man 
durch die zeugs.h umgehen, die die Funktionsprototypen enthält.

Nur #include "zeugs.h" im Hauptprogramm, ohne die zeugs.c im Makefile zu 
erwähnen würde also nicht funktionieren.

Ist das soweit richtig.. ? :-)

Vielen Dank und nen schönen Abend noch :-)
Christian
Persönliche Seite #924537
Lesenswert?

Gast123 wrote:
> Nur #include "zeugs.h" im Hauptprogramm, ohne die zeugs.c im Makefile zu
> erwähnen würde also nicht funktionieren.
>
> Ist das soweit richtig.. ? :-)

Jep genau. Das Kompilieren würde zwar funktionieren, aber beim Linken 
meldet der Linker dann, dass er bestimmte Objekte (also die Funktionen), 
die der Compiler in das Objectfile eingtragen hat, nicht finden kann.
Gast #924963
Lesenswert?

Demzufolge muss man das makefile also immer anpassen. Bisher dachte ich, 
das wäre nur bei Änderung am Prozessortyp oder der Taktfrequenz 
notwendig.

Juhu, ich glaub ich habs verstanden :-)

Vielen Dank an alle fleißigen Erklärer :-)

Gruß und noch ein schönes Wochenende
Christian
Gast #926082
Lesenswert?

Momentan verwende ich WinAVR. Das AVR-Studio hatte ich vor einer Weile 
für ASM benutzt, aber seit einem Weilchen soll das ja auch C verstehen. 
Werd ich demnächst ausprobieren. Wobei die Modifikation am Makefile nun 
auch nicht die große Sache ist - wenn man erstmal kapiert hat dass und 
warum es erforderlich ist :-)

Gruß
Christian

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren