Forum: Compiler & IDEs Frage zum Aufteilen von C-Programm in mehrere Dateien


von Johannes B. (johannes_b32)


Lesenswert?

Hallo,

mal eine Frage. Typisches Problem, ich möchte ein ATmega-Programm (in C) 
in mehrere Dateien aufteilen. Es gibt eine main.c, eine RS232.c und 
RS232.h. In die main.c und RS232.c wird RS232.h eingebunden. Der 
Compiler meckert aber bei der RS232.c, dass keine RS232.h existiert. Nur 
bei der einen, sonst keine Fehler.

Weiß evtl. jmd. woran's liegt?

Gruß, Johannes

von Helmut L. (helmi1)


Lesenswert?

Johannes B. schrieb:
> Der
> Compiler meckert aber bei der RS232.c, dass keine RS232.h existiert. Nur
> bei der einen, sonst keine Fehler.

Sind die Include Pfade richtig gesetzt?

von Toff (Gast)


Lesenswert?

Falls Du ein eigenes makefile benutzt, hast Du da die RS232.c 
eingetragen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Johannes B. schrieb:
> Der Compiler meckert aber bei der RS232.c, dass keine RS232.h existiert.

Wie sind die Dateien im Dateisystem verteilt?

Sind die *.h-Dateien in anderen Verzeichnissen als die *.c-Dateien 
untergebracht?

Wie genau sieht die #include-Anweisung aus?

von Johannes B. (johannes_b32)


Lesenswert?

also ich hab die RS232.h und -.c im Projektordner, wo auch die main.c 
ist, und habe die Dateien im solution explorer unter "Add" eingetragen.

Den Ordner zu den Include/Pfaden hinzufügen? .... ich finde leider die 
Einstellung nicht wo die Pfade angegeben werden ..

Die Include-Anweisungen:
main.c:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/sleep.h>
4
#include <string.h>
5
#include <stdio.h>
6
7
#include <RS232.h>

RS232.c:
1
#include <RS232.h>

von Konrad S. (maybee)


Lesenswert?

Header, die nicht zum System (d.h. Compiler) gehören, includiert man mit 
Anführungszeichen, nicht mit Kleiner-/Größer-Zeichen.
1
#include "RS232.h"

von Helmut L. (helmi1)


Lesenswert?

Johannes B. schrieb:
> Den Ordner zu den Include/Pfaden hinzufügen? .... ich finde leider die
> Einstellung nicht wo die Pfade angegeben werden ..

Wenn es AVR Studio ist.

Project -> Configuration Options -> Include Directories

Dort neuen Pfade anlegen wo die *.h Files liegen.

Also entweder:

<rs232.h>  mach "rs232.h" aendern    (liegt dann im Arbeitsverzeichnis)

oder den Pfad ergaenzen.  siehe oben.

von Johannes B. (johannes_b32)


Lesenswert?

okay vielen dank schonmal soweit!
Noch eine Frage zu den allgemeinen Bibliotheken. Der Compiler meckert 
jetzt, dass er in der RS232.c einige Register nicht kennt. Aber ich will 
ja nicht unbedingt in der RS232.c noch alle Bibliotheken includieren
1
{
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/sleep.h>
5
#include <string.h>
6
#include <stdio.h>
7
}

.. Das mache ich ja schon in der main.c:
1
{
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/sleep.h>
5
#include <string.h>
6
#include <stdio.h>
7
8
#include "RS232.h"
9
}

kann ich das umgehen oder muss das so bleiben?

von Konrad S. (maybee)


Lesenswert?

1.) Lass die Klammern um die include-Direktiven weg, die haben da nichts 
zu suchen!
2.) Die include-Direktiven holen nur Header-Dateien rein, d.h. machen 
Deklarationen bekannt. Sie fügen keine Definitionen (d.h. Code oder 
Daten) ein. Also musst du die include-Direktiven auch in der RS232.c 
drinhaben.

von Johannes B. (johannes_b32)


Lesenswert?

ok vielen dank euch allen!

von Rosa-Kleidchen (Gast)


Lesenswert?

>Sie fügen keine Definitionen (d.h. Code oder
>Daten) ein. Also musst du die include-Direktiven auch in der RS232.c
>drinhaben.
Nach nunmehr 20 Jahre C-Erfahrung würde es mich wundern, wenn #include 
nicht genau das macht, was es machen soll: Den Inhalt der Datei genau 
dahin einfügen! Folgende Stolpersteine sind schon oben genannt worden:
- Mache dem Compiler die Header-Verzeichnisse bekannt
- Header-Dateien mit Anführungsstriche setzen

Damit hatte ich noch nie Probleme!
Rosa

von Karl H. (kbuchegg)


Lesenswert?

Rosa-Kleidchen schrieb:
>>Sie fügen keine Definitionen (d.h. Code oder
>>Daten) ein. Also musst du die include-Direktiven auch in der RS232.c
>>drinhaben.
> Nach nunmehr 20 Jahre C-Erfahrung würde es mich wundern, wenn #include
> nicht genau das macht, was es machen soll

Du missverstehst das 'Problem'.
Viele Anfänger denken, dass ein #include ihnen bereits die 
Funktionalität, die Funktionen selber, reinzieht. Sie wissen schlicht 
und ergreifend nicht, dass es sowas wie Systembibliotheken gibt, die 
automatisch dazugelinkt werden bzw. haben keine Vorstellung davon dass 
es entweder einen Linker gibt bzw. was der eigentlich macht.
Das andere 'Problem' besteht darin, dass sie nicht wissen, dass jedes 
C-File unabhängig von allen anderen compiliert wird. Und da kommt es 
dann schon mal vor, dass die Fragestellung durchschlägt: Ich hab das 
doch in main.c sowieso schon inkludiert, warum muss ich das in xyz.c 
nochmal inkludieren?

Das ganze ist also eigentlich weniger ein technisches Problem sondern 
ein Problem des Wissens über die Vorgänge, die dazu führen, dass ein 
komplettes Programm zusammengebaut wird.

von Nik D. (y2kicn)


Lesenswert?

Evt. ist folgendes Schema hilfreich. - Ich mache das jeweils
um in mittelgrossen Projekten auf einfache Weise doppelte includes zu 
vermeiden und trotzdem die Übersicht zu bewahren.

Angenommen ich habe eine main.c, a.c, b.c a.h, b.h.

Ich generiere immer zusätzlich noch eine includes.h:

includes.h:
1
#ifndef __PROJEKTNAME
2
#define __PROJEKTNAME
3
4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
#include <avr/sleep.h>
7
#include <string.h>
8
#include <stdio.h>
9
//usw, was ich halt so brauche
10
11
#include "a.h"
12
#include "b.h"
13
14
#endif

main.c, a.c, b.c :
1
#include "includes.h"

a.h, b.h:
1
//Keine Includes mehr, nur noch func prototypes und defines der dazugehoerigen .c files

von Peter II (Gast)


Lesenswert?

Nik D. schrieb:
> Evt. ist folgendes Schema hilfreich.

naja bei großen Projekten nicht sinnvoll.

1. compilieren dann zu lange dauert weil immer alles Header verwendet 
werden.
2. wenn eine Headerdatei geändert wird, werden alles C quellen neu 
compiliert auch wenn sie gar nicht davon abhängig sind.

Bei kleinen Projekten ok, bei großen schlechte Idee.

von Rosa-Kleidchen (Gast)


Lesenswert?

>#ifndef __PROJEKTNAME
>#define __PROJEKTNAME
das guard-macro ist immer zu empfehlen, um zu verhindern, dass 
Header-Files in Header-Files Probleme verursachen.

>Du missverstehst das 'Problem'.
hmm. Wenn der Prä-Prozessor auf das macro '#include' trifft, wird der 
Inhalt der Datei an diese Stelle kopiert. Erst danach wird das 
Objekt-File aus diesem modifizierten C-File erzeugt. Ist das nicht 
korrekt? Es ist für Anfänger wissenswert, das es einen Prä-Prozessor 
gibt, der zuerst einmal Macros auflöst.

>Und da kommt es
>dann schon mal vor, dass die Fragestellung durchschlägt: Ich hab das
>doch in main.c sowieso schon inkludiert, warum muss ich das in xyz.c
>nochmal inkludieren?
ok.
Rosa

von Nik D. (y2kicn)


Lesenswert?

>>naja bei großen Projekten nicht sinnvoll.

Genau so sehe ich das auch, deswegen hab ich ja auch geschrieben bei 
mittelgrossen Projekten (soll heissen ~max 20 source files / 20 header)

Ich denke gerade wenn man die Sache mit den ifdef, ifndef und includes, 
welche in mehreren Sourcefiles gebraucht werden noch nicht so drauf hat 
ist es eine gute Alternative, damit das Zeug einfach mal compiliert.
Ich weiss noch wie ich make damals verflucht habe, als ich mit C 
angefangen habe und versucht habe mehrere C files aufs mal zu 
compilieren... ;-)

von Karl H. (kbuchegg)


Lesenswert?

Nik D. schrieb:
>>>naja bei großen Projekten nicht sinnvoll.
>
> Genau so sehe ich das auch, deswegen hab ich ja auch geschrieben bei
> mittelgrossen Projekten (soll heissen ~max 20 source files / 20 header)
>
> Ich denke gerade wenn man die Sache mit den ifdef, ifndef und includes,
> welche in mehreren Sourcefiles gebraucht werden noch nicht so drauf hat
> ist es eine gute Alternative, damit das Zeug einfach mal compiliert.

Das ist doch das kleinste Problem.
Wenn ein #include fehlt, dann gehts sowieso nicht durch den Compiler.

> Ich weiss noch wie ich make damals verflucht habe, als ich mit C
> angefangen habe und versucht habe mehrere C files aufs mal zu
> compilieren... ;-)

Einfache Regel:
lies den Code von oben nach unten - ein einziges mal.
Für alles was ausserhalb des Sprachstandards liegt muss es zumindest 
eine Deklaration geben. Entweder steht die direkt im gleichen 
C-File/H-File oder kommt über einen #include herein.
Macht man alle H-Files von vorne herein in sich vollständig, dann gibt 
es kaum Probleme. Von daher ist so ein Rundumschlag-include auch bei 
kleinen Projekten schon nicht sinnvoll. Enteder ich benutze Funktionen 
aus einer rs232.c im Code in einem C-File, dann muss auch rs232.h 
inkludiert werden. Oder ich tu das nicht, dann brauch ich auch den 
#include nicht.

Das eigentliche Problem ist die Denkweise, dass ich da ja ein 'Projekt' 
habe und wenn an einer Stelle ein Include ist, dann gilt der für das 
komplette Projekt. Für uns alte Hasen, die noch ohne IDE aufgewachsen 
sind, ist das völlig normal, dass es in C keinen Projektgedanken gibt - 
jedes C-File steht für sich alleine. Aber für die aktuelle Generation, 
die nicht mehr mit Command-Line gearbeitet hat, ist das alles andere als 
naheliegend.

von apr (Gast)


Lesenswert?

Nik D. schrieb:
> #ifndef __PROJEKTNAME
> #define __PROJEKTNAME

"All identifiers that begin with an underscore and either an uppercase 
letter or another underscore are always reserved for any use."

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.