Forum: Compiler & IDEs Atmel Studio Code auslagern


von Indi (Gast)


Lesenswert?

Hallo ich versuche gerade meinen Code auszulagern.

Es geht um ein .c file in dem sich Funktionen wiederfinden.

Im Hauptfile wird diese ausgelagerte mit #include "ReadTemp.c" 
aufgerufen. Ich bin mir nicht sicher aber ich glaube alle benötigten 
include müssen im ausgelagerten .c file auch noch stehen weil der eine 
von dem anderen vor dem linken nichts voneinander weiß stimmt das so ?

Leider wirft mir Atmel Studio aber dennoch Fehler raus....


"
ReadTemp.c:In function 'SensorRead'
ReadTemp.c:7:2: error: 'Heitzung_Temp' undeclared (first use in this 
function)
ReadTemp.c:each undeclared identifier is reported only once for each 
function it appears in
Error compiling

"
Kann mir dabei wer helfen ?

Gruß

von Sebastian V. (sebi_s)


Lesenswert?

Hier scheint so einiges durcheinander zu gehen. Erstmal included man 
keine .c Dateien sondern nur .h Header. Schreibe also eine entsprechende 
Headerdatei für deine ReadTemp.c Datei mit Deklarationen aller 
Funktionen.

Woher die Fehlermeldung kommt kann ich jetzt auch nicht herausfinden. 
Aber es ist sicher kein Linkerfehler. Den Linker interessiert es 
überhaupt nicht welche Header du eingebunden hast. Der Compilerfehler 
deutet aber auf eine fehlenden Header hin.

: Bearbeitet durch User
von Indi (Gast)


Lesenswert?

Für Klassen ect. habe ich das natürlich so umgesetzt und die .h Datei 
includiert.
Bei einfachen Funktionen wollte ich mir das sparen.
Aber das müsste doch so funktionieren oder nicht ?

von Sebastian V. (sebi_s)


Lesenswert?

Nein du kannst nicht einfach .c Dateien includen. Theoretisch kopiert 
ein include ja nur den Dateiinhalt an die entsprechende Stelle wo das 
#include stand. Wenn du das mit .c Dateien machst wird Atmel Studio aber 
wohl auf die Idee kommen die ReadTemp.c genauso zu compilieren wie deine 
main.c und wenn alles Ende gelinked wird gibts einen Linkerfehler wegen 
doppelt definierter Funktionen.

Wenn man doch mal eben schnell eine Funktion in eine extra Datein 
auslagern will und kein .c/h. Paar erstellen will dann macht man nur 
eine .h Datei und definiert alle Funktionen als inline. Aber niemals nur 
eine .c Datei.

von Falk B. (falk)


Lesenswert?

@ Indi (Gast)

>Für Klassen ect. habe ich das natürlich so umgesetzt und die .h Datei
>includiert.

Klassen, soso. Du bist also so fit und wissend, dass du C++ beherrschst, 
nur bei den elementaren C-Grundlagen hapert es ein wenig?

>Bei einfachen Funktionen wollte ich mir das sparen.
>Aber das müsste doch so funktionieren oder nicht ?

Nö. Da werden dann "lustig" mehrere Funktionen mit gleichem Namen 
erzeugt und der Linker ist leicht irritiert. Mach es einfach richtig und 
ordentlich. Es werden AUSSCHLIELICH .h Datein per #include eingebunden, 
welche die Headerinfos der Funktionen der zugehörogen .c Dateien 
enthalten.

"Der preiswerteste und schnellste Weg etwas zu tun ist, es gleich 
richtig zu tun."

(Hab ich heute wieder mal gelernt 8-0)

von Indi (Gast)


Lesenswert?

Du hattest recht, mit der .h funktionierts . Gruß

von Karl H. (kbuchegg)


Lesenswert?

Indi schrieb:
> Für Klassen ect. habe ich das natürlich so umgesetzt und die .h Datei
> includiert.
> Bei einfachen Funktionen wollte ich mir das sparen.
> Aber das müsste doch so funktionieren oder nicht ?

Im Prinzip ja.

Aber wahrscheinlich vermutest du da wieder mal irgendeine Wunderwuzzi 
Funktionalität hinter dem #include.
Ein #include ist eine ganz einfache Sache:

Er wird vom Präprozessor bearbeitet, der an dieser Stelle im Code ganz 
einfach den Inhalt der angegebenen Datei einsetzt. Und erst das Ergebnis 
dieser Ersetzung geht dann an den eigentlichen Compiler. Ein #include 
ist nicht mehr als eine reine Textverarbeitungssache. Mehr passiert 
dabei nicht.

Hast du Code in einer Datei main.c
1
void foo()
2
{
3
  mach was;
4
}
5
6
void bar()
7
{
8
  mach was anderes;
9
  foo();
10
}
11
12
int main()
13
{
14
  bar();
15
}

und lagerst du die Funktion bar in eine eigene Datei bar.inc aus (ich 
nenn das absichtlich nicht bar.c, eben weil hier die Funktion selbst 
drinnen steht, die Datei aber nicht eigenständig compiliert werden 
soll), dann hast du in main.c
1
void foo()
2
{
3
  mach was;
4
}
5
6
#include "bar.inc"
7
8
int main()
9
{
10
  bar();
11
}

und bar.inc
1
void bar()
2
{
3
  mach was anderes;
4
  foo();
5
}

Der Präprozessort schnappt sich die main.c und stösst irgendwann auf das
1
...
2
#include "bar.inc"
3
...

das ist für ihn das Signal, diese Zeile rauszuwerfen und durch den 
Inhalt der Datei bar.inc zu ersetzen. D.h. der Präprozessor führt die 
beiden Einzelteile zusammen und erhält als Ergebnis den Text
1
void foo()
2
{
3
  mach was;
4
}
5
6
void bar()
7
{
8
  mach was anderes;
9
  foo();
10
}
11
12
int main()
13
{
14
  bar();
15
}
den er dann an den eigentlichen C Compiler weiter gibt. Alles bestens.

Hast du das main.c aber so aufgebaut
1
#include "bar.inc"
2
3
void foo()
4
{
5
  mach was;
6
}
7
8
int main()
9
{
10
  bar();
11
}

dann führt die Text-Einsetzung logischerweise zu
1
void bar()
2
{
3
  mach was anderes;
4
  foo();
5
}
6
7
void foo()
8
{
9
  mach was;
10
}
11
12
int main()
13
{
14
  bar();
15
}
und wenn wir uns das ansehen, dann sehen wir, dass von oben nach unten 
gelesen aus bar heraus eine Funktion foo() aufgerufen wird, von der zum 
'Zeitpunkt' des Aufrufs noch nichts bekannt ist, weil sie ja im 
Endergebnis unter der Funktion bar steht ohne dass es einen Prototypen 
dafür gab. Und dann gibt es eben von deinem Compiler eine entsprechende 
Warnung bzw. Error.

Fazit: ein #include ermöglicht dir, Einzelteile deines Codes auf mehrere 
Dateien aufzuteilen, die in Textform vom Präprozessor wieder 
zusammengesetzt werden, ehe das so erhaltene Machwerk dann zum Compiler 
geht.

Wie du diese Aufteilung machst, ist deine Sache. Das interessiert weder 
den Präprozessor noch den Compiler. Nur muss nach dem Präprozessor 
gültiger C Code rauskommen.

Und ja: die übliche Form ist es, Funktionen in getrennt compilierbare 
C-Files zu stecken, für die man dann ein Header File schreibt, welches 
includiert wird. Dieses Vorgehen hat sich bewährt, auch wenn es nicht 
vorgeschrieben ist und es durchaus auch Abweichungen davon geben kann 
und gibt.

Aber grundsätzlich kann man den Präprozessor einfach nur als eine Art 
Texteditor ansehen, der deinen Quelltext bearbeitet, ehe dann das 
erhaltene Machwerk zum Compiler geht. Sinnigerweise stehen die 
Anweisungen an diesen Texteditor im Text, den dieser spezielle Editor 
bearbeitet. Aber recht viel mehr steckt da nicht dahinter.

: Bearbeitet durch User
von Indi (Gast)


Lesenswert?

Indi schrieb:
> Du hattest recht, mit der .h funktionierts . Gruß

Okay es geht doch nicht, ich war zu schnell mit der Antwort

.h
"

#include "TempRead.h"

void TempRead() {

   Pool_Temp.requestTemperatures();
   Heitzung_Temp.requestTemperatures();
}
"

.c

"
// TempRead.h

#ifndef _TEMPREAD_h
#define _TEMPREAD_h

#include "arduino.h"
//-------SourceFile------------
#include "OneWire.h"          // One Wire Source
#include "DallasTemperature.h"      // Dallas Temperatur Source für One 
Wire Sensor DS18s20


void TempRead();


#endif
"

Das ist hier alles was ich bisher habe

von Indi (Gast)


Lesenswert?

.c und .h sind vertauscht...

von Karl H. (kbuchegg)


Lesenswert?

Indi schrieb:

Wenn wir uns nur und ausschliesslich dieses C++ File ansehen
1
#include "TempRead.h"
2
 
3
void TempRead() {
4
5
   Pool_Temp.requestTemperatures();
6
   Heitzung_Temp.requestTemperatures();
7
}

wer oder was ist "Pool_Temp"?
Wer oder was ist "Heitzung_Temp"?

Jedes C-File (oder bei dir eben C++ File) wird für sich alleine 
compiliert und muss für sich alleine gesehen vollständig sein!

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.