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
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?
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?
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:
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.
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.) 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.
>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
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.
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
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.
>#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
>>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... ;-)
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.
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."