Hallo! Ich schreibe gerade mehrere kleine Progrämmchen, die vielfach die selben Funtionen brauchen und in verschiedenen Unterverzeichnissen sitzen. Sind Metaheuristiken für die Uni. Ist das noch im Rahmen des Korrekten, wenn ich nun für die gemeinsamen Funktionen folgendes mache: Der Header ../meine_libs/lib1.h enthält #include "lib1.c" welche im selben Ordner wie der Header liegt. Bei einem kleinen Test hat es ohne zu meckern funktionier (gcc).
Nein, das ist Pfusch. Sobald nämlich die Headerdatei von zwei unterschiedlichen Stellen eingebunden wird, wird der Code doppelt eingebunden, und das wiederum ergibt Linkerfehler.
Hallo, nein, das ist nicht gut so. Code darf nur in den Header, wenn es sich um C++ Templates handelt. Du benutzt ja die Header Informationen um den Inhalt deiner *.c Datei in deiner aktuellen Datei bekannt zu machen. Den Rest erledigt der Linker für dich. Grüße,
Wenn du keine Lust hast, deine Lib zu linken, dann mach den Include halt in einem deiner .c-Files. Aber das ist mit hoher Wahrscheinlichkeit immer noch Quatsch - aber wenigstens funktionierender Quatsch.
> Code darf nur in den Header, wenn es sich um C++ Templates handelt.
Stimmt so nicht ganz. Code darf und muss in den Header wenn es sich um
inline-Funktionen oder -Methoden handelt. (inline Funktionen gibt es
auch in C99). Templates sind ein Spezialfall davon - die muss man inline
schreiben wenn man sie nicht explizit dort instanziieren will, wo man
sie definiert.
Dieser Code ist dann aber i.d.R. nicht in einer Datei mit Endung .c -
Die haben in einem Header normalerweise nichts verloren.
Rufus Τ. Firefly schrieb: > Nein, das ist Pfusch. > > Sobald nämlich die Headerdatei von zwei unterschiedlichen Stellen > eingebunden wird, wird der Code doppelt eingebunden, und das wiederum > ergibt Linkerfehler. So pauschal kann man das nicht sagen. Ich hatte vor Urzeiten mal eine Latte von Funktionsaufrufen, die immer mit denselben konstanten Parametern, aber verschiedenen Funktionen aufzurufen waren. Ich habe das dann so gelöst, daß ich die Aufrufe mit einem Fantasie-Funktionsnamen in eine Datei geschrieben und diese Datei dann includet habe. Vor dem jeweiligen include stand ein #define, das den Fantasienamen auf den richtigen Funktionsnamen umdefiniert hat und hinten dran ein #undef. Das Ganze stand im Rumpf einer Funktionsdefinition und definierte selbst natürlich nichts global sichtbares. Das sah zwar nicht so wahnsinnig schön aus, hatte aber den unschätzbaren Vorteil, daß der ganze Mist nur einmal gepflegt werden mußte und um das Konstrukt von den üblichen Header-Dateien abzuheben, hieß es auch nicht .h Von Generatoren, wie lex, yacc, bison etc. wird auch kein schönerer Code produziert, aber dort mault keiner rum, das sei "Pfusch".
Also wenn man sich z.B. die Sourcen von AeroQuad ansieht: https://code.google.com/p/aeroquad/source/browse/#svn%2Ftrunk%2FAeroQuad%2FAeroQuad dann wird man schnell merken warum Code in Header-Dateien nicht unbedingt zur Übersichtlichkeit beiträgt. In Header-Files gehören nur defines, Prototypen etc. aber keine kompletten Funktionen. In Header-Dateien erwartet einfach niemand, dass dort komplette Funktionen stehen, weil sie dort einfach nicht hin gehören. Header-Dateien bilden/definieren die Schnittstelle zwischen einzelnen Funktionseinheiten, aber die Implementierung (also die Funktionen selbst) gehören in die c/cpp-Datei. Ansonsten könnte man ja auch nicht richtig mit (vorkompilierten) libraries etc. arbeiten.
Timmo H. schrieb: > In Header-Files gehören nur defines, Prototypen etc. aber keine > kompletten Funktionen. In Header-Dateien erwartet einfach niemand, dass > dort komplette Funktionen stehen, weil sie dort einfach nicht hin > gehören. inline spricht dagegen. Klar "darf" man c files in die Header-Files einbinden, dem cpp ist das Wurscht. Nur ist es reiner Pfusch, wie Rufus schon sagte. Rufus Τ. Firefly schrieb: > Sobald nämlich die Headerdatei von zwei unterschiedlichen Stellen > eingebunden wird, wird der Code doppelt eingebunden, und das wiederum > ergibt Linkerfehler. Das würde sich mit ifdefs unterbinden lassen. Grüsse, René
Rene H. schrieb: > Das würde sich mit ifdefs unterbinden lassen. Nein. Deine "include guards" funktionieren nur innerhalb einer "translation unit", Programme bestehen aber üblicherweise aus mehreren davon. Und somit wäre der betreffende Code mit seinen Symbolen in jeder "translation unit" enthalten, und der Linker bekommt diese Symbole entsprechend mehrfach zu sehen. gcc enthält die unappetitliche Möglichkeit, mehrfachdefinierte Variablen zu einer zusammenzufassen (was den Fehler kaschiert, Variablendefinitionen in Headerdateien unterzubringen), aber glücklicherweise lässt sich das abstellen.
Timmo H. schrieb: > In Header-Dateien erwartet einfach niemand, dass > dort komplette Funktionen stehen, weil sie dort einfach nicht hin > gehören. Nenn sie anders, als .h und das Problem ist keins mehr... > In Header-Files gehören nur defines, Prototypen etc. aber keine > kompletten Funktionen. Brave Kinder popeln nicht ;-)
Uhu Uhuhu schrieb: > Nenn sie anders, als .h und das Problem ist keins mehr... Nein. Augenverschließen steigert nicht die Unsichtbarkeit.
Zu den inlines hat hier noch keiner eine Lösung gesagt wie es anderst gehen soll als den Code IN die .h zu schreiben.
Die inlines sind doch gerade die Ausnahme von der Regel "kein Code in Header-Dateien", von daher kann und soll es da nicht anders gehen.
Um die Anzahl der Ausnahmen zu reduzieren, würde ich einfach die Regel anders formulieren:
1 | In Header-Files kommt nichts, was Code- oder Datenbytes im Object-File |
2 | erzeugt. |
Deklarationen, Templates, Inline-Funktionen und Makro-Definitonen erzeugen keine Bytes, also dürfen sie in die Header-Files.
Rufus Τ. Firefly schrieb: > Nein. Augenverschließen steigert nicht die Unsichtbarkeit. Na ja, Konstruktionen wie
1 | #define XMACRO(x, y, z) DoSomething(y) |
2 | #include "generatormacros.m" |
3 | #undef XMACRO |
waren bei mir immer so auffällig, daß sie nicht übersehen wurden - ganz im Gegensatz zu so manch anderer "koscherer" Konstruktion... Mit Macros kann man natürlich viel Unsinn machen - wie mit jedem Küchenmesser auch. Aber wenn man keine hat, wie z.B. bei C#, dann können gewisse Aktionen doch zu ziemlich stupiden Schreibaufgaben entarten. Die Sprache läßt jedenfalls fast alles zu, so lange die Blockschachtelungstiefe durch den include-File nicht verändert wird.
Halte Dich einfach an die Standards und bedenke das die Wartbarkeit eines Programms von seiner Struktur abhängt. Wenn dann irgendwo was klemmt und der Debugger auf einmal im Headerfile nichts findet kommt die große Freude auf. Die Frage ist halt was erreicht werden soll ? Willst Du sowas haben:
1 | #if SYSTEM_1
|
2 | # include "system_1.h"
|
3 | #elif SYSTEM_2
|
4 | # include "system_2.h"
|
5 | #elif SYSTEM_3
|
6 | ...
|
7 | #endif
|
Wobei bei jedem header das passende c dazugelinkt wird. Das makefile bietet da allerdings wesentlich mächtigere Möglichkeiten. Und was halt verwundert, warum mußt Du die Funktion mehrfach einbinden ? Soweit ich Dich verstanden habe mußt Du mehrere Programme mit der gleichen Bibliothek erstellen. Was macht denn:
1 | #include <stdio.h> |
Für Dich wäre es doch sinnvoller:
1 | #include "meinpfad/meinheader.h" |
in jedes Programm einzubringen oder verstehe ich gerade Dein Problem nicht ? Achso jetzt kapiere ich gerade den "Faulheitsfaktor" :-P Schreibe Dir ein Shellmakro das die makefiles anpaßt und gut ist ...
Rufus Τ. Firefly schrieb: > Rene H. schrieb: >> Das würde sich mit ifdefs unterbinden lassen. > > Nein. Deine "include guards" funktionieren nur innerhalb einer > "translation unit", Programme bestehen aber üblicherweise aus mehreren > davon. Und somit wäre der betreffende Code mit seinen Symbolen in > jeder "translation unit" enthalten, und der Linker bekommt diese > Symbole entsprechend mehrfach zu sehen. > > gcc enthält die unappetitliche Möglichkeit, mehrfachdefinierte Variablen > zu einer zusammenzufassen (was den Fehler kaschiert, > Variablendefinitionen in Headerdateien unterzubringen), aber > glücklicherweise lässt sich das abstellen. Nö. Der cpp bindet das exakt einmal ein. Wenn es an der richtigen Stelle steht funktioniert das. Wenn Du mit "translation units" libraries meinst, ja, dann fällt der Linker auf die Schnauze. Ein Symbol darf nun mal nur einmal vorkommen. Aber das war nicht die Fragestellung. Ohne Libs funzt das, auch wenn es nicht sauber ist. Die Konventionen sind gegeben. Grüsse, René
Rene H. schrieb: > Ohne Libs funzt das, auch wenn es nicht sauber ist. Das sind Common-Blocks. Wenn mehrere mit gleichem Namen gefunden werden, wird jeweils die größte Version eingebunden. Fortran benutzt das seit Urzeiten. Es ist halt wie fast immer: Wer nicht weiß, was er tut, kann nicht damit rechnen, daß das dabei herauskommt, was er sich erträumt und dieses Geschwätz von "Sauberkeit" bedient sich seit Jahrzehnten immer mal wieder anderer Features, die verteufelt werden. Invariante ist aber stets, daß diejenigen, die sich seiner bedienen, bestenfalls Halbwisser sind...
Uhu Uhuhu schrieb: > Rene H. schrieb: >> Ohne Libs funzt das, auch wenn es nicht sauber ist. > > Das sind Common-Blocks. Wenn mehrere mit gleichem Namen gefunden werden, > wird jeweils die größte Version eingebunden. Fortran benutzt das seit > Urzeiten. > > Es ist halt wie fast immer: Wer nicht weiß, was er tut, kann nicht damit > rechnen, daß das dabei herauskommt, was er sich erträumt und dieses > Geschwätz von "Sauberkeit" bedient sich seit Jahrzehnten immer mal > wieder anderer Features, die verteufelt werden. > > Invariante ist aber stets, daß diejenigen, die sich seiner bedienen, > bestenfalls Halbwisser sind... Ich weiss was ich tue. Was willst Du mir genau sagen? Grüsse, René
Rene H. schrieb: > Wenn Du mit "translation units" libraries meinst, ja, dann fällt der Wenn du nicht weißt, was translation units sind, dann lern doch erstmal, bevor du hier im Brustton der Überzeugung Behauptungen aufstellst. > Ohne Libs funzt das, auch wenn es nicht sauber ist. Nein, mit "Libs" hat das nichts zu tun.
Stefan Rand schrieb: > Rene H. schrieb: >> Wenn Du mit "translation units" libraries meinst, ja, dann fällt der > > Wenn du nicht weißt, was translation units sind, dann lern doch erstmal, > bevor du hier im Brustton der Überzeugung Behauptungen aufstellst. > >> Ohne Libs funzt das, auch wenn es nicht sauber ist. > > Nein, mit "Libs" hat das nichts zu tun. Gut ja, damit hast Du recht. Grüsse, René
Stefan Rand (srand) schrieb: Rene H. schrieb: >> Wenn Du mit "translation units" libraries meinst, ja, dann fällt der > Wenn du nicht weißt, was translation units sind, dann lern doch erstmal, > bevor du hier im Brustton der Überzeugung Behauptungen aufstellst. Dann erklärs ihm doch einfach und labere nicht von oben herab.
Translation Unit schrieb: > Stefan Rand (srand) schrieb: > > Rene H. schrieb: >>> Wenn Du mit "translation units" libraries meinst, ja, dann fällt der > >> Wenn du nicht weißt, was translation units sind, dann lern doch erstmal, >> bevor du hier im Brustton der Überzeugung Behauptungen aufstellst. > > Dann erklärs ihm doch einfach und labere nicht von oben herab. Danke Dir :-). Die Rüge habe ich allerdings wohl verdient. Ich hab das gegoogelt. Das ändert allerdings an meiner Aussage lediglich das keine libs gemeint sind sondern eben objs. Und ja, auch wenn ich seit 24 Jahren Software schreibe, diesen Ausdruck kannte ich nicht. Man lernt nie aus. Grüsse, René
Aber apropos labern, @Stefan Rand, weisst Du denn was "translation units" sind? Wenn ja, dann verwirrt Deine Aussage, dass es nichts mit libs zu tun hat. Grüsse, René PS: bei Stackoverflow Thema: According to standard C++: A translation unit is the basic unit of compilation in C++. It consists of the contents of a single source file, plus the contents of any header files directly or indirectly included by it, minus those lines that were ignored using conditional preprocessing statements. A single translation unit can be compiled into an object file, library, or executable program. The notion of a translation unit is most often mentioned in the contexts of the One Definition Rule, and templates.
Rene H. schrieb: > @Stefan Rand, weisst Du denn was "translation units" sind? Wenn ja, dann Natürlich. > verwirrt Deine Aussage, dass es nichts mit libs zu tun hat. Inwiefern?
> A single translation unit can be compiled into an object file, library, > or executable program. Grüsse, René
Ja und? Genauso kannst du behaupten, das ASCII oder elektrischer Strom etwas mit Libraries zu tun haben.
Stefan Rand schrieb: > Ja und? Genauso kannst du behaupten, das ASCII oder elektrischer Strom > etwas mit Libraries zu tun haben. Ich habe kein Problem damit, einzugestehen das ich falsch lag. Nach Deinem dafürhalten tat ich das. Trotzdem wäre ich froh, wenn Du mir erklärst, was falsch ist. Ich habe in meinem Post ja bereits deutlich gemacht, dass ich nicht weiss was •translation units" sind. Vielleicht findest Du die Zeit mir das zu erklären. Grüsse, René
Was ist eigentlich dein Problem mit mir? Du schreibst "Wenn Du mit "translation units" libraries meinst". Ich weise darauf hin, daß die beiden Begriffe keine Synonyme sind, sondern unabhängig voneinander. Was soll ich dir noch erklären? Sags mir, ich versteh nicht, was du willst.
Stefan Rand (srand) schrieb: > Was soll ich dir noch erklären? Sags mir, ich versteh nicht, was du > willst. Mein Gott, Mr. "Herr Allwissend" Stefan Rand (srand), dann erkläre ihm doch endlich den Begriff "Translation Unit". Das sollte doch einem der sich so forsch hier in die Diskussion einschaltet anfürsich leicht fallen oder etwa doch nicht?
Zur Hand habe ich gerade nur C, nicht C++: A source file together with all the headers and source files included via the preprocessing directive #include is known as a preprocessing translation unit. After preprocessing, a preprocessing translation unit is called a translation unit. Weiter unten heißt es dann In the set of translation units and libraries that constitutes an entire program [...] Und was hilft das jetzt?
Translation Unit schrieb: > Mein Gott, Mr. "Herr Allwissend" Stefan Rand (srand), dann erkläre ihm > doch endlich den Begriff "Translation Unit". Nochmals Danke für die Hilfe. :) Die war wohl nötig. Stefan Rand schrieb: > Und was hilft das jetzt? Das ich verstehen kann was Du mit: Stefan Rand schrieb: > Nein, mit "Libs" hat das nichts zu tun. exakt meinst. Jetzt verstehe ich die Begrifflichkeit dank Deiner Erklärung. Wie gesagt, ich kannte den Begriff nicht und auch meine Kollegen, egal ob Jung oder Alt konnten mit dem nichts anfangen. Bevor Du ausholen willst, nein, das sind mitnichten Pfeifen. Stefan Rand schrieb: > Was ist eigentlich dein Problem mit mir? Mit Dir habe ich kein Problem, weshalb auch. Man kennt sich ja nicht. Dennoch, Danke für die Erklärung der Begrifflichkeit. Ich kann es trotzdem nicht lassen (sorry, Rufus, wenn es gegen die Regel ist, dann lösch das Posting): Der Hochmut der Kleinen besteht darin, immer, der Großen, nie von sich selbst zu sprechen. [Voltaire] Grüsse, René
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.