1. Macht es Sinn grundsätzlich zu jedem ".c"-Sourcefile ein ".h"-File
mit anzulegen (egal, ob's benötigt wird oder nicht)?
2. Was hat es für Nachteile, wenn grundsätzlich jede Funktion (egal,
ob sie lokal oder global benötigt wird) als extern deklariert wird?
3. Ist es sinnvoll alle "includes" in einer seperaten Datei abzulegen,
und dann im entsprechenden Sourcefile nur diese eine Datei zu
includieren, anstatt in jedem Sourcefile eine Liste der Dateien
anzulegen, die wirklich benötigt werden?
Beispiel:
"ALLINCLUDES.H": #include "source1.h"
#include "source2.h"
#include "source3.h"
"SOURCE1.C": #include "allincludes.h"
"SOURCE2.C": #include "allincludes.h"
"SOURCE3.C": #include "allincludes.h"
4. Verwendet Ihr "ungarische Notation"?
P.S.: Ist mir schon klar, dass vieles Geschmacksache ist ;-)
ungarische Notation... die altert mir zu schnell. Bleibt zu überlegen, sie jeweils erst zu einem Release automatisch generieren zu lassen, falls sie gewünscht wird.
Gast
#708505
> 1. Macht es Sinn grundsätzlich zu jedem ".c"-Sourcefile ein ".h"-File > mit anzulegen (egal, ob's benötigt wird oder nicht)? Noe, aber es macht sinn so zu programmieren das es benoetigt wird! > 2. Was hat es für Nachteile, wenn grundsätzlich jede Funktion (egal, > ob sie lokal oder global benötigt wird) als extern deklariert wird? Du solltest nur Funktionen die auch in anderen Teilen deines Programms benoetigt werden ueber das Headerfile exportieren. Einer der Vorteile darin ein Project in kleine Sourcefiles aufzuteilen besteht darin das du diese Files irgendwann man in verschiedenen Projekten verwenden kannst. Es koennte dir dann passieren das du verschiedene Funktionen gleichen Namens hast. Das ist zwar generell nicht so empfehlenswert, aber wenn so eine Funktion nur lokal benutzt wird is es IMHO okay. > includieren, anstatt in jedem Sourcefile eine Liste der Dateien > anzulegen, die wirklich benötigt werden? Immer nur das importieren was du brauchst! Du musst dir darueber im klaren sein was dein Programm benoetigt und was nicht. Gib nicht das denken in automatischen Structuren ab indem du einfach alles importierst. Es kann z.B interessant enden wenn du irgendwo in deinem Header ein #define stehen hast das du vor Jahren mal geschrieben hast und woran du nicht mehr denkst, das die jetzt aber deinen Source umschreibt ohne das du es merkst. > 4. Verwendet Ihr "ungarische Notation"? Noe, aber ich esse auch keine kleinen Kinder. :-) Olaf 4. Verwendet Ihr "ungarische Notation"? 4. Verwendet Ihr "ungarische Notation"? 4. Verwendet Ihr "ungarische Notation"? 4. Verwendet Ihr "ungarische Notation"?
Gast
#708508
> 4. Verwendet Ihr "ungarische Notation"? > 4. Verwendet Ihr "ungarische Notation"? > 4. Verwendet Ihr "ungarische Notation"? > 4. Verwendet Ihr "ungarische Notation"? Nein, ich stottere noch nicht. Das sind einfach die Nachteile eines primitiven HTML-Interfaces im vergleich zu einem guten Newsreader mit Emacs als Editor. <seufz> Olaf
Gast
#708514
>Nein, ich stottere noch nicht. Das sind einfach die Nachteile eines >primitiven HTML-Interfaces im vergleich zu einem guten Newsreader >mit Emacs als Editor. <seufz> Kannst es nur nicht richtig bedienen.....
Gast
#708535
> Macht es Sinn grundsätzlich zu jedem ".c"-Sourcefile ein ".h"-File Ich halte nichts davon, aber das hängt vom Editor ab (wenn der falten kann, ist die Aufteilung in viele h-Files sehr hinderlich, aber bei einem Editor ohne dieses Feature verliert man in langen h-Dateien die Übersicht, dann sind kleine h-Dateien zu bestimmten Schwerpunkten übersichtlicher). Was mir ein grosser Graus ist: trivialer Code, der durch sinnfreie Kommentare und Unterteilung in 25 Header auf das zehnfache aufgebläht wurde und erst übersichtlich und verständlich wird, wenn man das Kommentar-Gestrüpp gelöscht hat und alle Header zusammenfasst. > Was hat es für Nachteile, wenn grundsätzlich jede Funktion (egal, ob sie lokal oder global benötigt wird) als extern deklariert wird? Für kleine Projekte sehe ich keine Nachteile. Die Übersichtlichkeit ("diese Funktion wird nur lokal benötigt") gewinnt dadurch nur minimal. > Ist es sinnvoll alle "includes" in einer seperaten Datei abzulegen und dann im entsprechenden Sourcefile nur diese eine Datei zu includieren Jede Sourcedatei mit einer unterschiedlichen Aufreihung von Includes zu beginnenen, wirkt auf mich etwas chaotisch. Besser ist es, alles in eine defs.h zu packen und (nur) diese in jedem Source-Code des Projekts zu inkludieren. Wenn der verwendete Compiler vorkompilierte Header unterstützt, kann man so den Compilevorgang stark verkürzen. > 4. Verwendet Ihr "ungarische Notation"? Das ist was für Erbsenzähler.
Gast
#708548
@dietmar >Jede Sourcedatei mit einer unterschiedlichen Aufreihung von Includes zu >beginnenen, wirkt auf mich etwas chaotisch. Besser ist es, alles in eine >defs.h zu packen und (nur) diese in jedem Source-Code des Projekts zu so mache ich das mittlerweile schon seit einigen jahren. alle benötigten includes in einer header datei rein (bei mir heißt die dann lib.h) und von jedem c-file aus wird diese datei included. geht gut und verursacht keine probleme >inkludieren. Wenn der verwendete Compiler vorkompilierte Header >unterstützt, kann man so den Compilevorgang stark verkürzen. das geht nicht nur mit vorkompilierten headern. es ließen sich ja auch alle c-files (z.b. in einer lib.c) includieren. ist aber nicht sehr ratsam (obwohl deutlich schnellere compilierzeiten)
Dietmar E wrote: >> Ist es sinnvoll alle "includes" in einer seperaten Datei abzulegen und dann im > entsprechenden Sourcefile nur diese eine Datei zu includieren > > Jede Sourcedatei mit einer unterschiedlichen Aufreihung von Includes zu > beginnenen, wirkt auf mich etwas chaotisch. Besser ist es, alles in eine > defs.h zu packen und (nur) diese in jedem Source-Code des Projekts zu > inkludieren. Wenn der verwendete Compiler vorkompilierte Header > unterstützt, kann man so den Compilevorgang stark verkürzen. > Dann hast du noch nie mittlere bis grosse Projekte bearbeitet. Denn da ist das, was du da erzählst absoluter Schwachsinn. Ein mittleres Projekt beginnt bei mir bei ca. 500 *.c/*.h Files. Ein grosses bei etwa 1000.
Gast
#708557
> das geht nicht nur mit vorkompilierten headern. es ließen sich ja auch > alle c-files (z.b. in einer lib.c) includieren. ist aber nicht sehr > ratsam (obwohl deutlich schnellere compilierzeiten) Also fuer die Behauptung solltest du jetzt aber nochmal eine Erklaerung liefern. Meine Projekte bestehen je nach Groesse aus 20 bis 100 einzelnen Files. Wenn ich daran arbeite dann aender ich meist nur in 1-2Files was und dann werden auch nur die neu uebersetzt. Das geht erheblich schneller als ein make all. Olaf
Gast
#708567
Und noch 'ne Meinung: >1. Macht es Sinn grundsätzlich zu jedem ".c"-Sourcefile ein ".h"-File > mit anzulegen (egal, ob's benötigt wird oder nicht)? Radio Eriwan .. es kommt darauf an. Warum teilt man überhaupt den Code in mehrere Sourcefiles auf? Sinn macht das, wenn sich dadurch (evtl. wiederverwendbare) Funktionseinheiten, logische Funktionseinheiten, Libraries, o.ä. bilden lassen. Die .h-Files sind dann die "Interfacedefinitionen" dazu, welches den öffentlichen Teil der .c-Datei anderen per "extern ..." bekannt macht. Beispielsweise eine source-Datei lcd.c mit allen Funktionen zur Ansteurung eines lcds, dazu ein lcd.h. Ohne Interface ist keine sinnvolle Nutzung eines solchen Moduls möglich, also gehört zu jeder .c-Datei eine .h-Datei. Keine Regel ohne Ausnahme, manchmal ist es sinnvoll, zu mehreren .c-Dateien nur eine .h-Datei zu haben, z.B. bei libraries. >2. Was hat es für Nachteile, wenn grundsätzlich jede Funktion (egal, > ob sie lokal oder global benötigt wird) als extern deklariert wird? Bei einer sauberen Definition des Interfaces stellt sich die Frage nicht. Per "extern" wird genau das nach aussen sichtbar gemacht, was sichtbar sein soll. Mehr nicht. >3. Ist es sinnvoll alle "includes" in einer seperaten Datei abzulegen, > und dann im entsprechenden Sourcefile nur diese eine Datei zu > includieren, anstatt in jedem Sourcefile eine Liste der Dateien > anzulegen, die wirklich benötigt werden? Ich persönlich vermeide geschachtelte includes, wo immer möglich. >4. Verwendet Ihr "ungarische Notation"? Nö. Oliver
Gast
#708648
> Keine Regel ohne Ausnahme, manchmal ist es sinnvoll, zu mehreren > .c-Dateien nur eine .h-Datei zu haben, z.B. bei libraries. In diesem Sonderfall habe ich dann auch eine einzige Header Datei passend zu Libary. Dort werden dann aber die einzelnen Headerdateien des Libariesource includiert. So muss ich dann fuer eine Libary die ich benutzen will und die sich nur selten mal aendert nur ein include einfuegen, habe aber andererseits den Vorteil das sich die Datei immer auf dem aktuellesten Stand befindet wenn ich etwas an der Libary verbessern oder einfuegen sollte. Olaf
Gast
#708682
> Dann hast du noch nie mittlere bis grosse Projekte bearbeitet
Ich bin der Entwickler von CubicIDE, einer führenden C/C++
Entwicklungsumgebung für Amiga/MorphOS Computer, Umfang ca 300 MB,
Sourecode der Kern-IDE ca 8 MB (im Moment ist die Webseite leider
offline, Server-Problem). Ich habe vermutlich mehr Code geschrieben, als
alle Leute in diesem Thread zusammen :)
So, jetzt will ich auch noch mein Senf dazugeben. Ich persönlich finde, dass es Sinn macht, seinen Code in mehrere Source- und dazugehörige Header-Files zu unterteilen. Natürlich sollte man das auch nicht übertreiben und für jede Funktion ein Source- und Header-File anlegen. Aber man packt zum Beispiel die USART-Funktionen in ein C-File und ein dazügehöriges H-File und dann kann man seine Display-Lib auch in ein eigenes C-File und H-File packen und so weiter. So weiss man immer, aha, ich will eine USART-Funktio --> in zB. usart.h nachschauen und so weiter. Natürlich gehört auch zu jeder Funktion eine anständige Doku die jeden Parameter und auch den Return immer schön sauber beschreibt, so dass ich diese Funktionen auch noch in einem Jahr wieder verwenden kann, ohne zuerst genaustens meine Source studieren zu müssen. Und noch ein Wort zur ungarischen Notation. Ich persönlich verwende sie und finde, dass sie mir hilft, vorallem auch beim Coden. Es ist jedoch nicht das wichtigste um einen übersichtlichen Code zu schreiben. Viel wichtiger ist, dass man jeder Variable einen sinnvollen Namen gibt. So, jetzt wisst ihr's ;-) Sputnik
Dietmar E wrote: >> Dann hast du noch nie mittlere bis grosse Projekte bearbeitet > > Ich bin der Entwickler von CubicIDE, einer führenden C/C++ > Entwicklungsumgebung für Amiga/MorphOS Computer, Umfang ca 300 MB, > Sourecode der Kern-IDE ca 8 MB (im Moment ist die Webseite leider > offline, Server-Problem). Und warum verzapfst du dann so einen Scheiss, dass es vernünftig ist alle includes in ein 'Ueber-Include' zusammenzufassen und nur dieses zu verwenden? Damit führst du jeden make bzw. jedes make Generiertool ad absurdum. Um mein letztes Projekt komplett zu compilieren, ist die Maschine etwas über eine Stunde beschäftigt. Wenn du wirklich wegen jeder kleinsten Änderung in jedem kleinsten Header File eine Compiletime von 1 Stunde akzeptabel findest anstelle von ein paar Sekunden bzw Minuten für nur die Teile die geändert wurden bzw. davon abhängig sind, dann .... > Ich habe vermutlich mehr Code geschrieben, als > alle Leute in diesem Thread zusammen :) Das du dich mal nicht täuscht.
Nachtrag: Aber vielleicht reden wir ja aneinander vorbei. Es geht um die Situation: 3 *.c Files foo1.c
1 | |
2 | |
3 | |
4 | |
5 | |
foo2.c
1 | |
2 | |
3 | |
4 | |
5 | |
main.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
samt zugehörigen Header Files: foo1.h
1 | |
2 | |
3 | |
4 | |
foo2.h
1 | |
2 | |
3 | |
4 | |
Ändere ich die Funktion foo2 um, so dass sie einen zusätzlichen int als Argument nimmt, dann wird vom make neu compiliert: foo2.c und main.c. Soweit so gut Führe ich aber einen Überheader ein def.h
1 | |
2 | |
und halte mich konsequent an die Vorgabe und tausche alle #includes in den *.c gegen ein #include "defs.h" aus und mache dieselbe Operation (int Argument einführen), was wird dann neu compiliert: foo1.c foo2.c main.c foo1.c wird völlig sinnlos neu compiliert. Bei ein paar mehr *.c Files fängt das an, ins Gewicht zu fallen, weil auf diese Art immer alle *.c neu compiliert werden. Jede Änderung in irgendeinem Header führt dazu, dass defs.h für make als veraltet gilt, und da alle *.c von defs.h abhängen, wird alles neu compiliert. Super. Disclaimer: Wie bereits gesagt, bei Libraries macht ein 'Über-Include' sehr wohl Sinn. Allerdings: Libraries ändern sich nicht sehr häufig, so dass das verschmerzbar ist, wenn die Maschine beim build rumrödelt. Das gilt aber nicht für normalen Source Code.
Gast
#708924
> Ich bin der Entwickler von CubicIDE, einer führenden C/C++ > Entwicklungsumgebung für Amiga/MorphOS Computer, Umfang ca 300 MB, > Sourecode der Kern-IDE ca 8 MB (im Moment ist die Webseite leider > offline, Server-Problem). Ich habe vermutlich mehr Code geschrieben, als > alle Leute in diesem Thread zusammen :) Ich persönlich bin ja ein Freund/Verfechter der Qualität, nicht der Quantität. Aber das soll Dich abhalten mehr Code zu produzieren. ;-)
Gast
#708987
Im Rahmen des Forums, in dem wir hier diskutieren, sollten wir vielleicht nicht Schwa... äh, Codegrößen vergleichen, sondern dem OP sagen, wie man es sinnvoll machen kann. Da in so einen ATMega64 definitiv nicht mehr als 64 kByte Code reinpassen, kann ein Projekt in jedem Fall übersetzt werden, ohne dass man Kaffee holen muss. Ich persönlich fange typischerweise auch erst mal mit einem Modul an, und wenn das Projekt umfangreicher wird, wird halt aufgeteilt in mehrere C-Module, die ggf. die notwendigen Header exportieren. Letztlich ergibt sich beispielsweise für das main-Modul kein eigener Header. Und ja, auch ich fasse alle Header in einer "defs.h" zusammen, weil's übersichtlich ist.
Gast
#709092
> Ich persönlich bin ja ein Freund/Verfechter der Qualität, nicht der Quantität Das schliesst sich nur für Anfänger gegenseitig aus. Qualität in kleiner Menge erzeugen könne viele. Qualität in sehr grosser Menge zu produzieren ist das Ziel. Meine Webseite ist inzischen wieder online, dort kannst Du dir ein Bild von der Qualität meiner Arbeit machen (http://devplex.awardspace.biz). Zum Thema globale Header-Datei: wenn man einen faltenden Editor verwendet, dann werden lange Dateien zu kurzen Dateien. Man sieht selten mehr als ein paar Zeilen: Wenn ich die Strukturen sehen will, klappe ich den Block mit den Strukturen auf. Wenn ich eine bestimmte Struktur suche, zeigt mir der Editor auf Knopfdruck eine Liste aller Elemente (Strukturen usw.) im Text an und ich kann sie dort auswählen. Dadurch, dass alles in einer Datei ist, ist alles blitzschnell anspringbar. Kein Wühlen durch zwanzig Header mit jeweils 8 Zeilen, garniert mit ellenlangen, hohlen Kommentaren. Der andere Vorteil einer zentralen Datei ist, dass Macros, Strukturen usw. garantiert konsistent über das ganze Projekt sind und dass Prototypen und globale Variablen überall zugriffsbereit sind. Man kommt nicht in die Versuchung, für jeden Teilbereich etwas Neues zu erfinden. Meine defs.h-Datei ist üblicherweise so aufgebaut: Compiler-spezifische Definitionen. Einbinden der System-Includes und der lokalen Include-Dateien (es gibt natürlich mehr als eine Header-Datei im Projekt, z.B. für Ressourcen wie Strings, aber nicht eine Header-Datei pro Quelltext). Definition der Macros. Definition/Enumeration der Konstanten. Definition der Strukturen. Definition der globalen Variablen. Funktions-Prototypen aller Module - wird automatisch aktualisiert. Alle diese Blöcke sind sinnvoll gefaltet: nach dem Laden der defs.h sehe ich etwa 10 Zeilen. Und zwar sinnvolle Zeilen ("Strukturen", "Definitionen", "Globals") und kein Murks wie lange Dateiköpfe. Hinter diesen 10 Zeilen verbergen sich im Fall von Cubic IDE 3800 Zeilen oder 160 KB. Durch einen guten Editor merkt man davon nichts: jeder Struktur, Konstante usw. ist in Sekunden anspringbar - meistens mit drei bis vier Tastatureingaben. Der erwähnte Aufbau ist natürlich nicht dogmatisch zu sehen. Konstanten, die zu Strukturen gehören, definiere ich beispielsweise in deren Nähe.
Gast
#709247
>Zum Thema globale Header-Datei: wenn man einen faltenden Editor >verwendet, (Rest der Werbung für eine bestimmte IDE gelöscht) Ich habe ja nun auch schon einige Zeilen Code geschrieben, aber einen faltenden Editor habe ich noch nie vermisst. Eine IDE, die den schnellen Zugriff auf alle Projektdateien ermöglicht, ist ja prima. Eine source-Datei, die nur "zusammengefaltet" verständlich wird, ist Murks. Aber das ist Geschmacksache. Oliver
Gast
#709273
Ich verwende i.d.R. nur einen Header. Allerdings lege ich Wert darauf, z.B. die Prototypen nach zugehörigen c-Dateien zu ordnen (+ Kommentar). Funktionen die aus anderen Modulen aufgerufen werden werden als extern deklariert, Funktionen die nicht geshared werden bekommen einen dementsprechenden Kommentar mit sachdienlichen Hinweisen. Globale Variablen werden grob geordnet und bekommen einen Kommentar in welchem Modul sie initialisiert/hauptsächlich benutzt werden. Wenn man allerdings so wie Karl eine Stunde compilieren muss, dann sollte man sich nochmal Gedanken machen ob es anders nicht sinnvoller wäre. Letztendlich ist das aber alles Geschmackssache.
Gast
#709276
> (Rest der Werbung für eine bestimmte IDE gelöscht) Himmelherrgott, das war keine Werbung. Als ob nur mein Editor falten könnte. Falten ist eine enorm nützliche Funktion, um den Überblick zu erhöhen, und wer darauf verzichtet, gehört bestraft. http://en.wikipedia.org/wiki/Folding_editor
Gast
#709303
>> es ließen sich ja auch >> alle c-files (z.b. in einer lib.c) includieren. ist aber nicht sehr >Also fuer die Behauptung solltest du jetzt aber nochmal eine Erklaerung >liefern. ich sagte es ist möglich. und ich denke unter gewissen umständen macht das evtl. sinn, z.b. wenn die sourcen innerhalb eines netzwerkes sind und viele leute darauf zugreifen/daran entwickeln, ist es evtl. (!) schneller das sich der compiler, der lokal auf dem rechner installiert ist sich erst alle c-dateien holt und nur eine datei compiliert, als zig oder 100'te dateien einzeln (übers netzwerk) zu compilieren. das argument das sich bei einer übergeordneten headerdatei (egal ob diese alle typen, prototypes in sich hat und es sonst keine weitere mehr gibt [bin ich allerdings auch kein fan von], oder "nur" weitere header dateien includiert werden) das projekt bei jeder kleinen änderung neu compiliert wird ok, aber wenns nicht allzugroße projekte sind ist diese lösung denke ich vor allem übersichtlicher. gruß rene
Gast
#709506
>es ließen sich ja auch >alle c-files (z.b. in einer lib.c) includieren. >wenn die sourcen innerhalb eines netzwerkes sind und viele leute darauf >zugreifen/daran entwickeln, Wenn in solch einem Fall keine Versionverwaltung wie CVS und Nachfolger zum Einsatz kommt, dürfte da nach spätestens zwei Tagen nichts kompilierfähiges mehr vorhanden sein, und das in 256 Versionen. Das wird nicht nur Murks, das wird Multiuser-Murks. Oliver
Meine Meinung: Gerade Anfängern sollte man auch im Hinblick auf ihren späteren Werdegang die Dinge vernünftig beibringen. Klar habt ihr recht, dass auf einem AVR mit den typisch relativ kleinen Codegrößen man das auch anders machen kann. ABer zuerst soll er doch bitte mal lernen, wie man das vernünftig macht, bevor man ihm die quick&dirty Variante zeigt. Wozu Einrückungen? Meine 20 Zeilen kann ich auch so überblicken. Wozu sprechende Variablennamen? Einbuchstabige tippen sich viel schneller und meine 10 Variablen kann ich auch so auseinanderhalten. Und dann kriegst du so einen in dein Team und must ihm erst mal Coding-Standards und Projektmanagement beibringen, obwohl er nach eigenen Aussagen schon 'seit Jahren C programmiert'. Und Dietmar: Das ganze hat nichts mit einer IDE oder den Fähigkeiten eines Editors zu tun. Apropos: Eine gute IDE unterstützt eine Codesuche. Da stelle ich den Cursor auf die Variable oder den Datentyp oder die Funktion von der ich Informationen brauche, drücke eine Taste und der Editor sucht mir das File und die Stelle wo das Zeugs definiert ist. Das reicht im Regelfall völlig aus um auch in großen Projekten nicht den Überblick zu verlieren.
Auf jeden Fall Headerfiles benutzen, und idealerweise zu jeder Source einen Header. Die Sache hat, mal abgesehen davon, dass man damit den Code in logische Einheiten aufteilen kann und neukompilieren deutlich schneller geht, den Vorteil, dass man zwangsweise ein paar mehr Überlegungen zur Programmstruktur anstellt. Normalerweise sollte man das zwar vorher machen, aber je kleiner die Projekte... also wenn man sich für einen neuen Funktionsblock erstmal im Header alle globalen Funktionen definiert die man dafür braucht und dabei mal kurz drüber nachdenkt wie das dann später funktionieren soll, hat man das Interface schonmal durchdacht, und Fehler fallen dann schnell auf. Außerdem kann man sich dann aussuchen in welcher Reihenfolge man den Code schreibt (bzw. wenn mehrere Leute dran schreiben kann gleichzeitig programmiert werden), weil die Funktionen schon spezifiziert sind. Der eine schreibt implementiert dann zB. die Funktionen, der andere schreibt schon an der Routine, die die Funktionen verwenden soll. PS: IDE -> offene Konsole + mehrere KWrite Instanzen auf verschiedene Desktops verteilt. Der Programmierer macht den Unterschied, nicht die IDE.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.