Guten Tag,
ich habe eine "Kinderfrage" - das muß eigentlich sehr einfach sein, aber
ich kapiere das noch nicht. Suche hat auch kein Ergebnis gebracht
(komischerweise).
Die Frage: wie verteilt man Programm auf mehrere Files?
Ich kenne #include, und soweit ich etwas auf ein *.h - File umplatziere
und danach mit #include in Haupttext einbinde - dann arbeitet alles so,
als ob der Inhalt zweiten Files direkt im Text wäre. Aber wenn ich
versuche, wie empfolen, in *.h nur #define und Prototypen von Funktionen
zu schreiben, und die Funktionen selbst in dem gleichnahmigen *.c -
File, dann klappt nichts. Nur Fehlermeldungen.
Ich denke, ich kann nicht richtig *.c und *.h zusammenbinden.
Ob jemand mir bitte erklären könnte, woran das liegt, oder noch besser
ein Link geben, wo Einbinden von anderen Files beschrieben wird?
Leider gibt meine Suche alles mögliches über C selbst, aber nichts über
Hantieren mit *.h und *.c.
Vielen Dank im voraus,
Maxim.
Maxim B. schrieb:> Nur Fehlermeldungen.
Profi-Tip: Die Fehlermeldungen haben sogar einen Text, den man lesen
kann. Lesen muss du den Text schon selber, denn wir kennen ihn nicht.
Maxim B. schrieb:> Aber wenn ich> versuche, wie empfolen, in *.h nur #define und Prototypen von Funktionen> zu schreiben, und die Funktionen selbst in dem gleichnahmigen *.c -> File, dann klappt nichts.
ALLE *.c Files müssen Teil vom Projekt sein.
Die Header kommen dann über die #include Anweisungen dazu.
JEDE *.c muss alle Header einbinden, in denen die Prototypen von
Funktionen stehen, welche in der jeweiligen *.c verwendet werden.
>> Profi-Tip: Die Fehlermeldungen haben sogar einen Text, den man lesen> kann.
Leider bringt das wenig: nur Info, daß das und das nicht definiert
wurde. Obwohl in Hauptfile schon alles da und allein mit *.h alles
arbeitet... Warum mit *.h wird alles richtig kompiliert und mit *.h und
*.c zusammen nicht? Wie bindet man diese Files zusammen?
Maxim B. schrieb:> Warum mit *.h wird alles richtig kompiliert und mit *.h und> *.c zusammen nicht? Wie bindet man diese Files zusammen?
zeige uns doch mal ein Beispiel wie du es gemacht hast.
Maxim B. schrieb:>>>> Profi-Tip: Die Fehlermeldungen haben sogar einen Text, den man lesen>> kann.> Leider bringt das wenig: nur Info, daß das und das nicht definiert> wurde.
Wenn es eine "undefined reference" Meldung ist, dann bringt die
Information sehr viel: Dann kommt die Fehlermeldung nämlich nicht vom
Compiler, sondern vom Linker.
Wie baust Du denn die Software? Mit einer bestimmten IDE? Mit selbst
geschriebenen makefiles? Anders?
> JEDE *.c muss alle Header einbinden, in denen die Prototypen von> Funktionen stehen, welche in der jeweiligen *.c verwendet werden.
Danke!
Bedeutet das, daß ich in *.c alle #include, die im Hauptfile schon
angegeben sind, wiederholen muß?
Ich weiß - das sind Kinderfragen. Aber noch dummer wäre es, nicht zu
fragen :)
Volker S. schrieb:> JEDE *.c muss alle Header einbinden, in denen die Prototypen von> Funktionen stehen, welche in der jeweiligen *.c verwendet werden.
...bzw. anders ausgedrückt: jede C-Datei muss einzeln übersetzbar
sein...
> Wie baust Du denn die Software? Mit einer bestimmten IDE? Mit selbst> geschriebenen makefiles? Anders?
Mit AVR Studio 4.18 Build 716. Und dazu WinAVR-20100110
Maxim B. schrieb:>> Wie baust Du denn die Software? Mit einer bestimmten IDE? Mit selbst>> geschriebenen makefiles? Anders?> Mit AVR Studio 4.18 Build 716. Und dazu WinAVR-2100110
Vielleicht sind nicht alle C-Dateien dem Projekt hinzugefügt. Das würde
ich mir mal als erstes anschauen.
Jede .c wird für sich selber übersetzt in ein Objectfile. Das macht der
Compiler
Dann werden die Objectfiles mit den Bibliotheken zu einem Ausführbaren
Programm gebunden. Das macht der Linker.
Deine IDE muss jetzt wissen, welche .c-Dateien (und Bibliotheken) zu
deinem Programm gehören. Dazu gibt es meist ein Project-Menü, in dem man
das machen kann.
Es geht auch mit der Hand, bzw etwas einfacher mit einem makefile.
Ich denke, das Problem liegt daran, daß ich in *.h und *.c falsche
Angaben mache.
Ich habe nun versucht, in "Nebenfile.c" alle #include zu machen.
Nun kommt folgende Spielerei:
wenn ich in *.h keine Variablen gebe und alle nur in Hauptfile, sagt
Compieler: undefinierte Variable in "Nebenfile.c".
Wenn ich aber die Variablen in *.h platziere und von beiden *.c includen
lasse, dann sagt Compieler "multiple definition".
Was mache ich falsch?
Nachtrag:
Zunächst mal sind globale Variablen nicht unbedingt empfehlenswert. Um
eine Mehrfachdefinition zu verhindern, bedient man sich eines so
genannten "Include Guards":
myfunction.h:
Noch ein Nachtrag:
Wenn du eine globale Variable in main.c anlegst, dann kannst du auch aus
anderen Modulen daraus zugreifen, wenn die Variable dem Modul vorher
bekannt gemacht wird:
main.c:
1
uint32_tMyVar=0;
nebenfile.c:
1
externuint32_tMyVar;
2
3
MyVar=12345ul;
Wie gesagt versucht man aber normalerweise, globale Variablen zu
vermeiden. Die Gründe und Argumente hierfür sind vielfältig. Bei Deinem
ersten C-Programm kann man aber wohl darüber hinwegsehen.
Dirk B. schrieb:> Bei Funktionsdeklarationen verzichtet man i.A. auf das extern.
Richtig, viele verwenden es nur bei Variablen. Eine alte Angewohnheit
von mir :)
In die Headerdatei kommen alle Informationen, die andere c-Dateien
brauchen um die Funktionen zu benutzen.
Mehr nicht.
Interne Funktionen, Variablen und Typen bleiben in der .c (und werden
als static definiert)
Maxim B. schrieb:> Wenn ich aber die Variablen in *.h platziere und von beiden *.c includen> lasse, dann sagt Compieler "multiple definition".> Was mache ich falsch?
Wenn du das machst, dann wird ja, wie du ganz oben schon selber gesagt
hast, der Text des Headers beiden *.c Dateien zugefügt.
Das ist also genau das gleiche, als ob du in beiden *.c die gleiche
globale Variable definierst.
"Definitionen" im Sinne von etwas, dass direkt Programmcode erzeugt oder
Speicherplatz reserviert, haben in einem Header nichts verloren!
Vielen Dank!
Um klarer zu machen, wo ich hinke, gebe ich hier die Dateien aus meinem
Probeprojekt:
Vielen Dank im voraus für Fehleranweisungen!
Hier geht es um ein Voltmeter für sehr rauscharme Umgebung, daher
statische LED.
Bestimmt fehlt mir noch Klarheit, was wohin gehört...
Maxim B. schrieb:> Bestimmt fehlt mir noch Klarheit, was wohin gehört...
Wenn du die Fehlermeldungen noch posten würdest, wäre alles viel
einfacher. Warum soll sich eigentlich jemand anderes die Mühe machen?
Build started 26.7.2016 at 13:26:38
avr-gcc -mmcu=atmega324pa -Wl,-Map=Voltmeter_2016_07_24_v3.map
Voltmeter_2016_07_24_v3.o Ind_stat.o -o Voltmeter_2016_07_24_v3.elf
Ind_stat.o: In function `vyvod':
D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik\2016_07_Voltmeter\Program
m\Voltmeter_2016_07_24_v3\default/../Ind_stat.c:12: multiple definition
of `zif1'
Voltmeter_2016_07_24_v3.o:D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik
\2016_07_Voltmeter\Programm\Voltmeter_2016_07_24_v3\default/../Voltmeter
_2016_07_24_v3.c:45: first defined here
Ind_stat.o: In function `vyvod':
D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik\2016_07_Voltmeter\Program
m\Voltmeter_2016_07_24_v3\default/../Ind_stat.c:12: multiple definition
of `zif2'
Voltmeter_2016_07_24_v3.o:D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik
\2016_07_Voltmeter\Programm\Voltmeter_2016_07_24_v3\default/../Voltmeter
_2016_07_24_v3.c:45: first defined here
Ind_stat.o: In function `vyvod':
D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik\2016_07_Voltmeter\Program
m\Voltmeter_2016_07_24_v3\default/../Ind_stat.c:12: multiple definition
of `zif3'
Voltmeter_2016_07_24_v3.o:D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik
\2016_07_Voltmeter\Programm\Voltmeter_2016_07_24_v3\default/../Voltmeter
_2016_07_24_v3.c:45: first defined here
Ind_stat.o: In function `vyvod':
D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik\2016_07_Voltmeter\Program
m\Voltmeter_2016_07_24_v3\default/../Ind_stat.c:12: multiple definition
of `zif4'
Voltmeter_2016_07_24_v3.o:D:\A_Radioelementen_Daten\ZZ_Projekt\Schematik
\2016_07_Voltmeter\Programm\Voltmeter_2016_07_24_v3\default/../Voltmeter
_2016_07_24_v3.c:45: first defined here
Ind_stat.o:(.data+0x0): multiple definition of `volt'
Voltmeter_2016_07_24_v3.o:(.data+0x0): first defined here
make: *** [Voltmeter_2016_07_24_v3.elf] Error 1
Build failed with 1 errors and 0 warnings...
Es tut mir leid, aber ich verstehe Englisch nur so halbwegs... mehrfache
definition von Var. - das ist mir klar. Aber warum und wie ist das zu
verbessern?
Maxim B. schrieb:> multiple definition of `zif1'Volker S. schrieb:> "Definitionen" im Sinne von etwas, dass direkt Programmcode erzeugt oder> Speicherplatz reserviert, haben in einem Header nichts verloren!
zif1 wird in einem Header "Definiert" ...
Volker S. schrieb:> zif1 wird in einem Header "Definiert" ...
Warum eigentlich überhaupt "global" bekannt machen?
Wird doch nur in einem einzigen *.c File verwendet.
Dann noch nicht mal in dem zugehörigen Header aufführen!
Es tut mir leid: ich kapiere immer noch nicht...
Wenn ich eine Var. in beiden *.c verwende - wo muß ich sie deklarieren?
In Hauptfile, in Nebenfile oder in Header?
Maxim B. schrieb:> Es tut mir leid: ich kapiere immer noch nicht...> Wenn ich eine Var. in beiden *.c verwende - wo muß ich sie deklarieren?> In Hauptfile, in Nebenfile oder in Header?
Deklarieren musst du sie in einem Header (mit extern davor).
Definieren in einer c-Datei.
Zu welchem Source gehöre die logisch?
Maxim B. schrieb:> Es tut mir leid: ich kapiere immer noch nicht...> Wenn ich eine Var. in beiden *.c verwende - wo muß ich sie deklarieren?> In Hauptfile, in Nebenfile oder in Header?
jede Variabel darf nur EINMAL deklariert werden. Damit kann es nicht in
einer Header Datei sein.
zu jeder .h gibt es meist eine .c und dort gehört die Variable rein.
Und es müssen nur Funktionen in der .h die außerhalb er .c genutzt
werden sollen.
Peter II schrieb:> jede Variabel darf nur EINMAL deklariert werden. Damit kann es nicht in> einer Header Datei sein.
Sie darf nur einmal definiert werden.
deklarieren kannst du sie, so ogft du willst.
Na, Danke an alle! Geklappt!
Aber ich sollte eine Zeile in Hauptfile ändern:
statt
OCR1B = volt; // PWM in Halbe
sollte ich schreiben
OCR1B = PWM_init/2; // PWM in Halbe
Dann blieb var. volt nur für Ind_stat.c und auch nur dort erklärt.
Nun läuft Programm als ob alles in einem File... Wie auch gedacht...
Aber trotzdem: wenn ich eine Var. in mehreren Files verwende, wo genau
und wie wäre sie zu deklarieren? Ich möchte das verstehen...
Maxim B. schrieb:> Na, Danke an alle! Geklappt!> Aber ich sollte eine Zeile in Hauptfile ändern:> statt> OCR1B = volt; // PWM in Halbe> sollte ich schreiben> OCR1B = PWM_init/2; // PWM in Halbe> Dann blieb var. volt nur für Ind_stat.c und auch nur dort erklärt.
Bravo ;-)
Maxim B. schrieb:> Aber trotzdem: wenn ich eine Var. in mehreren Files verwende, wo genau> und wie wäre sie zu deklarieren? Ich möchte das verstehen...
Da wo die Variable eben logisch hin gehört. Definiert wird sie in dem
logisch zugehörigen *.c File und im entsprechenden Header als extern
deklariert, damit der Compiler bei anderen *.c Files die diesen Header
einbinden weiß, dass es diese Variable irgendwo gibt und wie sie
Aussieht.
Da soll sich dann später der Linker darum kümmern, ob das alles so
wirklich passt ;-)
Maxim B. schrieb:> Aber trotzdem: wenn ich eine Var. in mehreren Files verwende, wo genau> und wie wäre sie zu deklarieren? Ich möchte das verstehen...
Wenn Du schon globale Variablen verwendest, dann sollten diese
wenigstens nur in einem einzigen Modul beschrieben werden. Dieses Modul
ist dann sozusagen der Besitzer dieser Variablen, hier wird der
Speicherplatz dafür angelegt. Die anderen Module lesen diese Variable
nur.
Noch besser wäre es, auf globale Variablen ganz zu verzichten - oder
zumindest überall da, wo es möglich ist.
Kauf Dir ein Buch über C-Programmierung!
Peter II schrieb:> jede Variabel darf nur EINMAL deklariert werden. Damit kann es nicht in> einer Header Datei sein.
Falsch.
Jede Variable kann so oft Du willst deklariert werden. Aber sie darf nur
einmal definiert werden.
Das ist die Definition:
int foo;
Das ist die Deklaration:
extern int foo;
Und das ist für einen C-Compiler kein Problem:
extern int foo;
extern int foo;
extern int foo;
extern int foo;
int foo;
Du hast offenbar Definition und Deklaration verwechselt.
Maxim B. schrieb:> Aber trotzdem: wenn ich eine Var. in mehreren Files verwende, wo genau> und wie wäre sie zu deklarieren? Ich möchte das verstehen...Volker S. schrieb:> "Definitionen" im Sinne von etwas, dass direkt Programmcode erzeugt oder> Speicherplatz reserviert, haben in einem Header nichts verloren!
Wenn du eine Funktion/Variable definierst, dann wird dafür Speicher
verbraucht.
Darf nur einmal gemacht werden. Das gehört in eine C-Datei
Wenn du eine Funktion/Variable deklarierst, dann gibst du dem Compiler
bekannt, das ein Objekt mit diesem Namen existiert. Kann oft gemacht
werden.
Das gehört in eine H-Datei, aber nur, wenn diese Information ausserhalb
der eigenen C-Datei gebraucht wird.
Da du aus main nur ismerenie und indikator aufrufst, brauchst du die
anderen Funktionen auch nicht in der H-Datei deklarieren.
Maxim B. schrieb:> Z.B. wenn eine Var. in ISR geändert wird und von vielen anderen> Funktionen abgefragt - wo und wie muß sie gefiniert werden?
Da würde ich auf das Main-C-File "tippen". Also die Datei, welche die
Definition der Funktion main() enthält.
Dann meinetwegen in einem Header Namens "global....h" als extern
deklarieren und diesen in allen C-Files einbinden die auf die Variable
zugreifen.
Grundsätzlich aber trotzdem überlegen, ob es nicht manchmal doch besser
ist, Variablen beim Funktionsaufruf zu übergeben.
Was um alles in der Welt soll "ismerenie" und "vyvod" bedeuten?
Funktionen und Variablen gibt man sinnvolle Namen. Wenn man das nicht
kann, dann sollte man vielleicht lieber Pommes am Bahnhof verkaufen.
Danke!
Ich habe in global.h geschrieben
extern volatile int volt;
und in
Ind_stat.c volatile int volt = PWM_init / 2;
weiter zurück gemacht bei Init in Voltmeter_2016_07_24_v3.c:
OCR1B = volt; // PWM in Halbe
Ist das so korrekt?
Programm scheint zu funktionieren, aber ich möchte für die Zukunft
wissen...
Über das Buch habe ich auch schon gedacht. Aber von Bildschirm leichter
zu lesen...
Es gibt viele Bücher und viel Kritik... Wenn ich nach PDFs beurteilen
darf, es gibt überall etwas Wichtiges, was nicht besprochen wird. Z.B.
über heutige Problem habe ich nirgendwo etwas gefunden... Obwohl ich
auch schon Bloodshed Dev-C++ installiert habe - um mit C als solcher
etwas vertrauter zu werden (obwohl mein Ziel ausschließlich
Mikrokontroller sind)...
Welches Buch wäre am besten?
Mark B. schrieb:> Was um alles in der Welt soll "ismerenie" und "vyvod" bedeuten?>
Als eingebürgerte Russe erlaube ich mir ab und zu auch mit russischen
Worten hantieren :) Für mich sind sie verständlich :) Ich bin in
Elektronik ein Liebhaber, schreibe eigentlich nur für mich selbst.
ismerenie heißt Messen
vyvod heißt Ausgabe.
Maxim B. schrieb:> Wenn ich eine Var. in beiden *.c verwende - wo muß ich sie deklarieren?> In Hauptfile, in Nebenfile oder in Header?
Modul1.c:
1
intVar=0;
Modul1.h:
[c}
extern int Var;
1
Modul2.c:
2
[c]
3
#include"Modul1.h"
4
...
5
Var=1;
Das ist jetzt nochmal exakt das Gleiche, das ich oben schon mal
beschrieben habe! Es gibt im Allgemeinen auch keine "Haupt- und
Nebenfiles". Die main() stellt lediglich den Einsprungpunkt dar, nicht
mehr und nicht weniger.
Mark B. schrieb:> Was um alles in der Welt soll "ismerenie" und "vyvod" bedeuten?
zif1..4 ist auch nicht viel besser.
Vielleicht das nächste mal in einem russischsprachigem Forum posten ;-)
Volker S. schrieb:> Vielleicht das nächste mal in einem russischsprachigem Forum posten ;-)
Danke für Tipp. Würde ich weiter ein russischer Bürger bleiben und in
Rußland leben, so würde ich so auch tun.
Maxim B. schrieb:> Volker S. schrieb:>>> Vielleicht das nächste mal in einem russischsprachigem Forum posten ;-)>> Danke für Tipp. Würde ich weiter ein russischer Bürger bleiben und in> Rußland leben, so würde ich so auch tun.
Sollte nur ein kleiner Wink mit dem Zaunpfahl sein. Es ist für die Leute
hier doch viel einfacher, wenn Namen von Funktionen und Variablen
verständlich sind. Du scheinst ja auf jeden Fall keine Probleme mit der
deutschen Sprache zu haben. Da ist es doch eine nette kleine zusätzliche
Übung auch deutsche Namen zu vergeben. (Ich versuche das zur Übung alles
auf Englisch)
Volker S. schrieb:
Es ist für die Leute
> hier doch viel einfacher, wenn Namen von Funktionen und Variablen> verständlich sind. Du scheinst ja auf jeden Fall keine Probleme mit der> deutschen Sprache zu haben.
Ich habe das auch nicht böse gemeint. Obwohl außer Thema - ich möchte
mit Dank sagen, daß Deutschland vielleicht einziges Land auf der Erde
bleibt, wo auch die Ausländer in der Hochschule kostenlos studieren
dürfen! Ohne dieser Option könnte ich hier nie sein...
Ja, ich habe vor dem Posten alle Kommentare auf Russisch für Kommentare
auf Deutsch ersetzt. Aber die Namen von Funktionen irgendwie verpaßt, zu
korrigieren... Ich wußte nicht, daß das so reizen kann...
Hier in Pritzwalk reagieren die Leute auf Russisch eher mit Nostalgie
und nie mit Abneigung.
Kommentar muß vor allem für mich selber so verständlich wie nur möglich
sein - davon ging ich aus.
Honk schrieb:> Modul1.c:int Var = 0;>> Modul1.h:extern int Var;>> Modul2.c:#include "Modul1.h"> ...> Var = 1;
Ich empfehle, Modul1.h zusätzlich auch in Modul1.c zu "inkludieren",
also:
Modul1.c:
1
#include"Modul1.h"
2
intVar=0;
Das hat einen - nicht auf Anhieb ersichtlichen - aber einfachen Grund:
So meckert der Compiler sofort, wenn man versehenlich eine Variable
inkonsistent definiert, z.B.:
Modul1.c:int Var = 0;
Modul1.h:extern double Var;
Modul2.c:#include "Modul1.h"
...
Var = 1;
Diese Situation fällt nicht auf! Im Programm passiert dann garantiert
nicht das erwartete!
Wenn aber das Include-Statement in jedem relevanten C-Modul steht:
Modul1.c:#include "Modul1.h"
int Var = 0;
... dann kann der Compiler sofort eine Fehlermeldung ausgeben.
Maxim B. schrieb:> Ich wußte nicht, daß das so reizen kann...
Also zumindest ich bin überhaupt nicht gereizt.
Da bin ich viel zu sehr abgehärtet von unseren Studierenden.
Wenn die einen Variablennamen mit zehn Zeichen vergeben, dann sind dann
oft max. zwei bis drei Zeichen dabei, welches die Variable und deren
Zweck irgendwie sinnvoll beschreibt. "Variable_1" oder so was sehe ich
auch recht häufig ;-)
<< Frank M. schrieb:
Ich habe mir das als Merkzettel geschrieben:
Modul1.c: Variable mit Wert
Modul1.h: extern Variable ohne Wert
Modul2.c: #include "Modul1.h" oder extern Variable ohne Wert
Modul1.c: zusätzlich als Prüfung: #include "Modul1.h" vor der Variable
mit Wert
Alles richtig?
Volker S. schrieb:> Also zumindest ich bin überhaupt nicht gereizt.
das ist gut. Ich habe mich zuerst so gewundert: bisher habe ich in etwa
10 Jahren in D. nur einmal oder zweimal überhaupt etwas erlebt, was man
annähernd als Unfreundlichkeit gegen Ausländern bezeichnen kann... :) In
TV erzählt man viel Schreckchen, das ist aber weit vom Leben entfernt...
Ja, ich verstehe schon: wenn man an die Studierende täglich etwas sagt
und wieder und immer noch und sie hören sowieso nicht... :)
Ich habe Musik studiert, bei uns ist das weniger stark geprägt, weil
Unterricht meistens 1:1 ist. Aber ich kann schon einen Dozenten gut
verstehen...
Maxim B. schrieb:> Modul1.c: zusätzlich als Prüfung: #include "Modul1.h" vor der Variable> mit Wert>> Alles richtig?
Jepp, so ist es richtig. Übrigens macht man es so auch für die
Definitionen/Deklarationen von Funktionen - also wenn man
modulübergreifend eine Funktion aufruft:
Modul1.c:
1
#include"Modul1.h"
2
3
intfoo(inta,intb)
4
{
5
bar(a,b);
6
}
Modul1.h:
1
externintfoo(int);
Modul2.h:
1
#include"Modul1.h"
2
...
3
foo(123);
Erst durch das include in Modul1.c fällt auf, dass die Funktion foo()
eigentlich zwei Parameter braucht.
Maxim B. schrieb:> Ja, ich verstehe schon: wenn man an die Studierende täglich etwas sagt> und wieder und immer noch und sie hören sowieso nicht... :)
Da hilft eigentlich nur der Blick in die Vergangenheit (so 25 Jahre)
und die Einsicht, dass es schon immer viel einfacher war aus eigenen
Fehlern zu lernen ;-)
Maxim B. schrieb:> Dann aber stimmt Prototyp und Funktion nicht mehr überein?
Ja. Das fällt nur auf, wenn Modul1.h auch in Modul1.c includiert wird.
Sonst ist der Prototyp einfach für die Katz.
Im Laufe der Software-Entwicklung kommt es immer wieder vor, dass
Funktionen um zusätzliche Parameter erweitert werden. Nur so merkt man,
dass man nicht alles andere vollständig angepasst hat. Es gibt noch
nichtmals einen Fehler vom Compiler und man sucht sich dumm und
dusselig.
Maxim B. schrieb:> ich möchte> mit Dank sagen, daß Deutschland vielleicht einziges Land auf der Erde> bleibt, wo auch die Ausländer in der Hochschule kostenlos studieren> dürfen!
Danke!
Das ist was leider viele nicht verstehen, du hast es wenigstens mal
benannt!
(ok rel. kostenlos, oder sind Studiengebühren wieder abgeschafft?)
Zu dem Sprachmix, ich hatte mal in einem Großraumbüro Prüfgeräte
entwickelt und die Prüfsoftware geschrieben,
es war kein Problem Gespräche am Nachbartisch in deutsch auszublenden
oder mitzuhören je nach dem (wir hatten durchaus Themenüberschneidungen
bei denen ein kollegialer Austausch sinnvoll war), aber wenn die
Kollegen auf türkisch anfingen zu reden konnte ich mich nicht mehr
konzentrieren, mein Kopf versuchte immer zu verstehen was geredet wurde,
ausblenden unmöglich.
Deswegen zur besseren Lesbarkeit hier für die meisten User zur späteren
Hilfestellung scheinen deutsche lesbare Vasiablen- und Funktionsnamen
sinnvoll.
Joachim B. schrieb:> Deswegen zur besseren Lesbarkeit hier für die meisten User zur späteren> Hilfestellung scheinen deutsche lesbare Vasiablen- und Funktionsnamen> sinnvoll.
Meiner Ansicht nach hinkt Dein Vergleich. Man muss die Variablen- und
Funktionsnamen ja nun nicht deshalb unbedingt auf türkisch schreiben.
Ich finde es zum Beispiel prägnanter...
1
voiddelay(intmsec)
2
{
3
...
4
}
zu schreiben als:
1
voidVerzoegerung(intmsek)
2
{
3
...
4
}
Diesen Mischmasch aus deutschen Bezeichnernamen und englischen
Schlüsselwörtern finde ich genauso anstrengend wie das Zuhören von
türkischsprachigen Tischnachbarn :-)
Aber dem kann man ja Abhilfe schaffen:
Frank M. schrieb:> Ich finde es zum Beispiel prägnanter...void delay (int msec)
ich auch, bin ganz deiner Meinung!
Frank M. schrieb:> GebeZurueck 0;> }>> Mir wird gerade schlecht....
mir auch!
aber wenn schon, denn schon
GEBE_ZURUECK = 0;
Frank M. schrieb:> #define GebeZurueck returnJoachim B. schrieb:> aber wenn schon, denn schon>> GEBE_ZURUECK = 0;
Nö.
GebeZurueck 0;
ergibt zurückübersetzt:
return 0;
Und das ist allemal besser als
return = 0;
:-)
Maxim B. schrieb:> Mark B. schrieb:>> Was um alles in der Welt soll "ismerenie" und "vyvod" bedeuten?>>> Als eingebürgerte Russe erlaube ich mir ab und zu auch mit russischen> Worten hantieren :) Für mich sind sie verständlich :) Ich bin in> Elektronik ein Liebhaber, schreibe eigentlich nur für mich selbst.>> ismerenie heißt Messen> vyvod heißt Ausgabe.
Nun ja. So hast Du halt einen Mischmasch:
-manches ist auf Englisch, z.B. PWM_init
-manches ist auf Russisch, z.B. ismerenie
-manches ist auf Deutsch, z.B. Null_volt
Wenn Du da noch durchblickst und es ein Projekt für Dich allein ist...
okay.
Sobald mehr als ein Entwickler ins Spiel kommt (also im beruflichen
Kontext fast immer), sollte man sich dann schon auf eine Sprache
einigen und die dann auch konsequent überall verwenden.
Frank M. schrieb:> Joachim B. schrieb:>>> aber wenn schon, denn schon>>>> GEBE_ZURUECK = 0;>> Nö.>> GebeZurueck 0;
war ein Tippfehler, ich meinte doch
#define GEBE_ZURUECK return
GEBE_ZURUECK 0;
Maxim B. schrieb:> Ich denke, ich kann nicht richtig *.c und *.h zusammenbinden.
Es ist eigentlich ganz einfach. Mit einem Eintrag #include "dateiname"
kannst du beliebige Dateien in deine C-Quelle einbinden. Ob sowas nun
auf .h endet oder irgendwie anders, ist im Grunde völlig egal. Das *.h
hat man sich lediglich angewöhnt.
Die Frage steht nun, was denn in so einer *.h Datei stehen muß. Antwort:
Alles, was die aufrufenden Programme von der C-Datei wissen müssen, auf
die sich die .h Datei bezieht. Und alles andere eben NICHT. Schreib also
nur das Nötigste in eine .h Datei hinein. Ausgenommen sind sinnvolle
Kommentare, die du oder ein anderer nach 5 Jahren immer noch versteht.
Beispiel: ein UART, also eine serielle Schnittstelle. Für sowas schreibt
man zumeist einen separaten Handler, damit sich höhere Programmschichten
nicht um die Einzelheiten der Schnittstelle kümmern müssen.
Im Treiber uart.c kommen z.B. vor:
void Char_Out(char c)
{ ...
}
und
char Char_In(void)
{ ...
}
und
void Init_Uart(long Baudrate)
{ ...
}
Also schreibt man sich eine Headerdatei uart.h, wo dann folgendes
hineinkommt:
/* UART-Anschluss von Maxim */
#ifndef Maxims_Uart
#define Maxims_Uart
extern void Char_Out(char c);
extern char Char_In(void);
extern void Init_Uart(long Baudrate);
#endif
Wenn eine andere C-Quelle, z.B. burtsev.c jetzt diese uart.h Datei
einbindet, dann kann man die Funktionen von uart.c dort in burtsev.c
benutzen, weil ja der Compiler alles weiß, was er zum Aufrufen von
Char_Out und so wissen muß. Obendrein weiß er, daß alle diese Funktionen
nicht in der burtsev.c vorkommen, sondern woanders stehen. Er wird
deswegen auch nicht meckern, daß ja die Funktionsrümpfe fehlen. Das
macht dann viel später der Linker, falls ihm was fehlt.
Man bindet normalerweise die eigene .h auch in die C-Quelle mit ein,
damit der Compiler die Konsistenz zwischen den Prototypen und den
eigentlichen Funktionen prüfen kann. Das "extern" stört dabei nicht. Das
mit dem #ifndef.. und #define dient dazu, bei Mehrfacheinbindung
derselben Headerdatei keine eventuellen Duplikate zu bekommen. Ist
normalerweise bei sauberer Programmierung überflüssig, aber ich mach
sowas immer und aus Prinzip.
Und wenn dein Treiber so etwas wie ein struct benötigt, was auch die
aufrufenden Programmteile kennen müssen, dann schreibt man die
Definition dieses struct's in die .h Datei. Wenn das aber was internes
ist, und alle anderen Programmteile davon nichts wissen müssen, dann
schreibt man es in die C-Quelle und nicht in die zugehörige .h hinein,
denn das würde nur den Rest der Welt verwirren.
Nochwas: Deine Frage ist durchaus KEINE Kinderfrage, sondern eine sehr
ernste Frage.
W.S.
Vielen Dank für die Erklärungen!
Das ist für mich sehr, sehr wert!
Ich werde sicher nie ein Profi in diesem Bereich, mein Unterhalt
verdiene ich an der Orgel - aber das alles macht mir viel Spaß!
Außerdem gibt es viele Kleinigkeiten, die nur ich alleine brauche oder
nur wenige Kollege - dann ist das nicht zu kaufen und nur selbst zu
basteln...
Mit *.h und *.c ist besonders wichtig, da die Klarheit hier auch die
Bibliotheke von Anderen zu nutzen ermöglicht. So wie i2c oder für
Indikator.
Vielen Dank!
Was die Sprache betrifft: innerlich sind das für mich keine zwei
Sprachen, sondern eine große Sprache, die Russisch und Deutsch mit
einschließt. Mit der Zeit geht es immer leichter, zwischen den Sprachen
umzuschalten, und irgendwann gibt es die Grenze nicht mehr... Auch wenn
bei mir herum in der Familie alles nur deutschsprachig ist... Da ich ein
Musiker bin, war alles für mich dadurch einfacher, weil die Noten auf
allen Sprachen gleich aussehen (nur in Buchstab-Notation gibt es
Unterschiede zwischen Englischen und Deutschen: die Engländer schreiben
komischerweise statt "H" "B" und statt "B" "B mit be" - das ist
gewöhnungsbedürftig!. Im russissprachigen Raum nutzt man deutsche
Variante (außer in Pop-Musik).
Frank M. schrieb:> WarteDochEinWeilchenUndPfeifSolangEinLiedchen ();
:))
Herrlich. Wenn die Syntax gleich von Anfanfg an so geplant gewesen wäre,
würde niemand mehr eine andere Sprache benutzen wollen.
MfG Paul
Maxim B. schrieb:> Was die Sprache betrifft: innerlich sind das für mich keine zwei> Sprachen, sondern eine große Sprache, die Russisch und Deutsch mit> einschließt. Mit der Zeit geht es immer leichter, zwischen den Sprachen> umzuschalten, und irgendwann gibt es die Grenze nicht mehr...
Naja, dann kannst du diese Fähigkeit nutzen, um Code zu schreiben, den
nur wenige Leute verstehen.
> Musiker bin, war alles für mich dadurch einfacher, weil die Noten auf> allen Sprachen gleich aussehen (nur in Buchstab-Notation gibt es> Unterschiede zwischen Englischen und Deutschen: die Engländer schreiben> komischerweise statt "H" "B"
Ich würde es umgekehrt sagen: Die Deutschen schreiben komischerweise
statt "B" "H". Ich hab mich schon in der Grundschule gefragt, warum um
alles in der Welt das H zwischen dem A und dem C steht und nicht das B.
Rolf M. schrieb:> warum um> alles in der Welt das H zwischen dem A und dem C steht und nicht das B.
Weil die musikalische Tradition in Deutschland sehr lang und tief ist.
Historisch war Tonleiter kein Dur oder moll, wie die meisten es heute
kennen, sondern gerade A-B-C-D-E-F-G. "H" kam erst viel später in
Gebrauch, deshalb hat nächste Zeichen bekommen, noch frei.
Andere länder (englichsprachigen) kennen keine so lange musikalische
Tradition wie Deutschland. Sie haben alles übernommen, wie Tonleiter
schon längst komplettiert wurde. Für die schien es einfacher, statt "H"
"B" zu schreiben, was die Profi in D. eher als mangelhafte Ausbildung
wahrnehmen.
Ich muss mal meinen Senf dazugeben, wenns OK ist...
Dieser Thread ist in meinen Augen der wichtigste zum Thema C
überhaupt!!!
Hier wird etwas behandelt was ich schon bestimmt 1 Million mal falsch
gemacht habe. Danke dafür!