Guten Morgen,
ich habe eine .c-Quelltext-Datei, die ausschließlich dazu dient,
Konstanten zu definieren. Diese Konstanten sind Strings und String
Arrays (Textelemente in Landessprache).
Parallel dazu gibt es natürlich eine .h-Datei, die alle Konstanten als
extern deklariert und dem Projekt zur Verfügung stellt.
Beide werden momentan separat gepflegt, und es wird langsam umständlich.
Gibt es eine Möglichkeit, die Konstanten (Deklarationen und
Definitionen) mit Bordmitteln an einer Stelle zu pflegen oder ist es
sinnvoller, ein Script zu schreiben, das die *.h-Datei aus der *.c-Datei
erzeugt?
Walter T. schrieb:> Gibt es eine Möglichkeit, die Konstanten (Deklarationen und> Definitionen) mit Bordmitteln an einer Stelle zu pflegen
Variablen als static in der .h definieren.
Durch das "static" wird auch bei mehrfachem #include nicht versucht, sie
mehrfach anzulegen.
Korrigiert mich bitte, wenn da ein Denkfehler ist:
Wenn ich jede Konstante als "static" deklariere, wird jeder Textstring
für jede *.c-Datei, in der er aufgerufen wird, erneut in das Binary
eingebaut.
Heißt das, daß ich dann zwingend auf Link-Time-Optimization angewiesen
bin, oder ist der Linker von sich aus intelligent genug, diese
Duplizierung wieder zu entfernen?
STK500-Besitzer schrieb:> Durch das "static" wird auch bei mehrfachem #include nicht versucht, sie> mehrfach anzulegen.
Dafür hat man doch den Include Guard.
Spricht etwas gegen gettext und Alternativen? Schau dir einfach ein paar
OpenSource Projekte an wie die das einbinden...
https://www.gnu.org/software/gettext/
Peter Pan schrieb:> Spricht etwas gegen gettext und Alternativen?
Ja. Es geht um einen Mikrocontroller ohne Dateisystem und nur um wenige
hundert Zeichenketten.
Walter T. schrieb:> Wenn ich jede Konstante als "static" deklariere, wird jeder Textstring> für jede *.c-Datei, in der er aufgerufen wird, erneut in das Binary> eingebaut.
Ich wusste doch, dass ich das noch schreiben sollte:
Die .c-Datei wird dadurch überflüssig.
Die komplette Initialisierung erfolgt in der .h:
1
staticconstchar[][2]={{"blablabla"},{"Tuuut"}};
das habe ich jetzt nicht getestet.
Vielleicht weiß jemand anders eine schönere Lösung.
Walter T. schrieb:> Peter Pan schrieb:>>> Spricht etwas gegen gettext und Alternativen?>> Ja. Es geht um einen Mikrocontroller ohne Dateisystem und nur um wenige> hundert Zeichenketten.
Brauchst du alle Konstanten zur Laufzeit oder kompilierst du für jede
Sprache eine eigene Firmware?
Steve schrieb:> Eigentlich wird der ganze Inhalt einer Include sowieso nur einmal> "eingelesen", wegen den include guards:
Nein! Einmal pro Translation Unit (.c -Datei die mit 1 Compileraufruf
übersetzt wird). Aber wenn der Header von mehreren .c -Dateien
inkludiert wird, ist er auch jedes Mal da! Woher soll der Compiler
wissen, dass beim übersetzen irgendeiner anderen .c -Datei ein
Inklude-Guard definiert wurde?
Walter T. schrieb:> Wenn ich jede Konstante als "static" deklariere, wird jeder Textstring> für jede *.c-Datei, in der er aufgerufen wird, erneut in das Binary> eingebaut.
Korrekt!
Peter Pan schrieb:> STK500-Besitzer schrieb:>> Durch das "static" wird auch bei mehrfachem #include nicht versucht, sie>> mehrfach anzulegen.>> Dafür hat man doch den Include Guard.
Der hilft hier überhaupt nicht. Die in der Headerdatei angelegten
Konstanten werden pro .c -Datei einmal angelegt.
Walter T. schrieb:> oder ist der Linker von sich aus intelligent genug, diese> Duplizierung wieder zu entfernen?
Manche Linker ja. Probier es am Besten einfach aus.
Man kann sich mit fiesen Tricks behelfen, à la:
constants.h:
1
#ifndef CONSTANTS_H_
2
#define CONSTANTS_H_
3
4
#ifdef IMPL_CONST
5
#define DEFCONST(decl,val) decl = val;
6
#else
7
#define DEFCONST(def,val) extern def;
8
#endif
9
10
IMPL_CONST(constchar*constmystr,"Hello!")
11
IMPL_CONST(constintfoo,42)
12
13
#endif
constants.c:
1
#define IMPL_CONST
2
#include "constants.h
Dann constants.h normal überall inkludieren, und constants.c normal
kompilieren und mit linken. Richtig toll ist das aber nicht...
Walter T. schrieb:> ich habe eine .c-Quelltext-Datei, die ausschließlich dazu dient,> Konstanten zu definieren. Diese Konstanten sind Strings und String> Arrays (Textelemente in Landessprache).>> Parallel dazu gibt es natürlich eine .h-Datei, die alle Konstanten als> extern deklariert und dem Projekt zur Verfügung stellt.
Parallele Pflege ist immer doof.
Pflege das ein EINE .def/.hc/.irgendwas ein - aus der du per Script .h
und .c erzeugst (z.B. per awk, m4, ...). Rule in's Makefile rein und
fertig.
Hallo,
warum so kompliziert mit .h und .c? Sind doch nur Konstanten, dafür
reicht ein Headerfile, soll doch sowieso wo inkludiert bekannt sein. Und
weil du in C programmierst definierst du sicherlich deine Konstanten mit
#define und damit werden die sowieso vom Präprozessor gnadenlos im
Quelltext 1:1 ersetzt. Das heißt von deinem Headerfile bleibt nichts
übrig und es gibt auch kein Overhead.
Die Linker Option wäre übrigens -flto gewesen.
Veit D. schrieb:> Und> weil du in C programmierst definierst du sicherlich deine Konstanten mit> #define und damit werden die sowieso vom Präprozessor gnadenlos im> Quelltext 1:1 ersetzt.
Was wenn es eine komplexere Konstante mit verschachtelten structs o.ä.
ist? Die überall einzusetzen ist sicher nicht so wahnsinnig effizient.
Strings können Linker zum Glück ganz gut de-duplizieren.
Ich würde mehrere .c und .h Dateien nehmen, und die dementsprechend
benennen, was drin ist. Dann sollte das eigentlich übersichtlich
bleiben. Oft ist es auch Man kann auch eine .h Datei machen, die diese
dann einfach alle mit #include einbindet.
Bei grösseren Texten, Bildern usw. würde ich, sofern man sie wirklich in
der Anwendung selbst drin haben muss, die .c und .h Dateien generieren
lassen.
Wenn du wirklich unbedingt einen einzigen Header willst, würde ich das
in eine Datei packen (ungetestet):
1
#define UNPACK(...) __VA_ARGS__
2
#ifndef DEFINE
3
#define DECDEF(T, V) UNPACK T = UNPACK V;
4
#else
5
#define DECDEF(T, V) extern UNPACK T;
6
#endif
7
8
DEF((constchardata[]),("Hello, World!"))
Sollte dann "extern const char data[];" generieren, wenn per #include
eingebunden, und 'const char data[] = "Hello, World!";' wenn vorher
'#define DEFINE' gesetzt wird. Bei den meisten Compilern kann man das
oft auch mit "-D" machen, dann braucht man keine separate Datei dafür.
Das mit den () und Unpack ist da, damit wenn man mal Kommas dort hat,
das nichts aus macht.
Anscheinend versucht der gcc ab -O1 automatisch einen "String Merge"
über Translation Units hinweg. Wichtig ist wohl nur das man die Strings
so
1
constchar*string="bla";
und nicht so
1
constcharstring[]="bla";
definiert. Es gäbe auch noch die Option "-fmerge-all-constants", dann
versucht er wohl generell alle Konstanten zu "mergen". Das ist aber
nicht mehr Standardkonform. Müsste man mal ausprobieren ob das auch mit
"static" klappt.
Walter T. schrieb:> oder ist es sinnvoller, ein Script zu schreiben, das die *.h-Datei aus> der *.c-Datei erzeugt?
Ich würde den Script das gleich aus Textdateien sowohl .c als auch .h
generieren lassen. Das hat dann noch den Vorteil, dass die Texte
problemlos auch von Nichtprogrammiererinnen übersetzt werden können.
Oder tatsächlich schauen, ob man gettext dafür MCU-mäßig umbauen kann,
aber dessen Infrastruktur gleich nachnutzen. Der "_"-Makro muss dann
halt auf eine interne Tabelle / Minidatenbank gehen statt aufs
Dateisystem.
Programmierer schrieb:> Veit D. schrieb:>> Und>> weil du in C programmierst definierst du sicherlich deine Konstanten mit>> #define und damit werden die sowieso vom Präprozessor gnadenlos im>> Quelltext 1:1 ersetzt.>> Was wenn es eine komplexere Konstante mit verschachtelten structs o.ä.> ist? Die überall einzusetzen ist sicher nicht so wahnsinnig effizient.> Strings können Linker zum Glück ganz gut de-duplizieren.
Wenn ich mir die AVR Controller typischen Headerfiles anschaue sind da
structs mit defines ohne Ende drin. Macht alles der Präprozessor.
Veit D. schrieb:> Wenn ich mir die AVR Controller typischen Headerfiles anschaue sind da> structs mit defines ohne Ende drin. Macht alles der Präprozessor.
Hast du ein Beispiel? Wenn der Compiler bei jeder Nutzung des Makros
eine temporäre Instant des struct anlegen muss...
Walter T. schrieb:> Gibt es eine Möglichkeit, die Konstanten (Deklarationen und> Definitionen) mit Bordmitteln an einer Stelle zu pflegen oder ist es> sinnvoller, ein Script zu schreiben, das die *.h-Datei aus der *.c-Datei> erzeugt?
Mach es einfacher: Die einzelnen Texte nicht exportieren, sondern dir in
der betreffenden Quelle eine Funktion schreiben, die den gewünschten
Text je nach Landessprache als Zeiger zurückliefert. Damit schrumpft
deine .h auf den Export nur eben dieser Funktion zusammen.
W.S.
Programmierer schrieb:> Veit D. schrieb:>> Wenn ich mir die AVR Controller typischen Headerfiles anschaue sind da>> structs mit defines ohne Ende drin. Macht alles der Präprozessor.>> Hast du ein Beispiel? Wenn der Compiler bei jeder Nutzung des Makros> eine temporäre Instant des struct anlegen muss...
Habe keines zur Hand. Ein AVR Headerfile ... Moment, da stehen jede
Menge defines aber in den structs sind keine defines, Mist, hätte wetten
können in den structs stehen auch defines drin. Ich nehme alles zurück.
Entschuldigung, vorm geistigen Auge in Gedanken dachte ich das wäre so.
Nur werden #defines nicht generell vom Präprozessor ersetzt egal wo die
stehen? Ist doch reine Textersetzung. Ein struct schränkt doch nur die
Verwendung bzw. ggf. die Sichtbarkeiten ein. Ich sehe erstmal keine
Einschränkungen für den Präprozessor.
Veit D. schrieb:> Nur werden #defines nicht generell vom Präprozessor ersetzt egal wo die> stehen?
Ja. und das ist ja das große Problem, dass die Macros nicht ge-scoped
sind. Dies ist einer der Gründe, warum man ihn bspw. in C++ los werden
will.
Betrachte den CPP als nicht-interaktiven Editor.
Walter T. schrieb:> Gibt es eine Möglichkeit, die Konstanten (Deklarationen und> Definitionen) mit Bordmitteln an einer Stelle zu pflegen oder ist es> sinnvoller, ein Script zu schreiben, das die *.h-Datei aus der *.c-Datei> erzeugt?
Die vermutlich schnellste Lösung ist es, durch eine Scriptsprache deiner
Wahl (Python bietet sich heutzutage an) *.c und *.h aus einem Markup
deiner Wahl (XML, json, yaml, ini) zu generieren. Sollte sich in unter
100 Zeilen ausgehen.
Programmierer schrieb:> Man kann sich mit fiesen Tricks behelfen, à la:
Es gibt noch die Variante eine dritte Datei einzuführen und die jeweils
in eine .c und .h Datei zu includen. Damit sind .c und .h Datei gleich
hässlich:
constants.c:
1
#define IMPL_CONST
2
#include "constants.data
constants.h:
1
#ifndef CONSTANTS_H_
2
#define CONSTANTS_H_
3
#undef IMPL_CONST
4
#include "constants.data
5
#endif
> Richtig toll ist das aber nicht...
Ja aber viel mehr kann C nun mal nicht.
vnnn schrieb:> Die vermutlich schnellste Lösung ist es, durch eine Scriptsprache deiner> Wahl (Python bietet sich heutzutage an) *.c und *.h aus einem Markup> deiner Wahl (XML, json, yaml, ini) zu generieren. Sollte sich in unter> 100 Zeilen ausgehen.
Wenn man auf alles verzichtet (Markup, Bequemlichkeit, Leerzeilen,
Kommentare, Multi-Line, ...) dann ist das ein Einzeiler .c -> .h:
Walter T. schrieb:> Parallel dazu gibt es natürlich eine .h-Datei, die alle Konstanten .....> dem Projekt zur Verfügung stellt.
Daten in *.h?
z.B. Strings, oder Variablen?
C kann das nicht wirklich.
C++ allerdings schon.
Ein Grund mehr C++ statt C zu verwenden.......
Peter Pan schrieb:> Brauchst du alle Konstanten zur Laufzeit oder kompilierst du für jede> Sprache eine eigene Firmware?
Es gibt für jede Sprachversion ein eigenes Binary. Ich gebe mich nicht
der Illusion hin, dass meine Projekte derart interessant sind, dass sie
international großes Interesse finden. Andererseits hat es sich
allerdings angeboten, alle sichtbaren Texte zentral zu halten, schon
allein um die Nutzerführung konsistent zu halten.
Ich habe mal einen Auszug zum IST-Zustand angehängt. Falls euch
Inkonsistenzen auffallen: Ja, genau, die waren der Anlass zur oben
gestellten Frage.
Will ich unbedingt eine einzelne Datei? Nein, das ist kein Muss. Ich bin
lediglich auf der Suche nach einer brauchbaren Praxis.
(Es passiert sonst zu leicht, dass man irgendetwas übersieht, was
ansonsten jeder zu wissen scheint. Es hätte mich z.B. nicht gewundert,
wenn automatisch generierte Header mittlerweile zum Standardrepertoire
von Build-Umgebungen gehörten und ich einfach nur nicht den korrekten
Suchbegriff gefunden hätte.)
Walter T. schrieb:> Es hätte mich z.B. nicht gewundert,> wenn automatisch generierte Header mittlerweile zum Standardrepertoire> von Build-Umgebungen gehörten und ich einfach nur nicht den korrekten> Suchbegriff gefunden hätte.
Nachdem ich eine Nacht drüber geschlafen habe, wäre ein Automatismus, .C
und .H-Dateien konsistent zu halten, genau etwas, was ich wirklich gerne
hätte, da es einiges an Scroll- und Schreibarbeit sparte.
Allerdings bin ich gerade absolut davon überfordert, wie das
Plugin-System in EmBitz funktioniert. Ich finde keine Doku. Es wird wohl
ein unerfüllter Traum bleiben.
EAF schrieb:> Walter T. schrieb:>> Parallel dazu gibt es natürlich eine .h-Datei, die alle Konstanten .....>> dem Projekt zur Verfügung stellt.>> Daten in *.h?> z.B. Strings, oder Variablen?>> C kann das nicht wirklich.> C++ allerdings schon.>> Ein Grund mehr C++ statt C zu verwenden.......
Ich packe meine Konstanten auch immer als Member in C++ Klassen. Dann
müssen sie noch über den Klassennamen noch angesprochen werden.
Für 2 unterschiedlichen Buffersize bei Ethernet und SPI gibt es dann
Ethernet::Buffersize
SPI::Buffersize
die auch andere Werte haben können.
Und statt gcc kann man im Makefile auch g++ benutzen, und schon hat man
diese Features.
PittyJ schrieb:> Ich packe meine Konstanten auch immer als Member in C++ Klassen.
Ich glaube es ging um C ;-)
PittyJ schrieb:> Und statt gcc kann man im Makefile auch g++ benutzen, und schon hat man> diese Feature
Womit man sich ein paar kleine Differenzen einhandelt.
Doch grundsätzlich stimme ich Dir natürlich zu und vertrete das ja hier
im Forum auch immer vehement, wofür ich ja dann auch mein Fett weg
bekomme ;-)
Ich sage ja immer, dass 90% des C-Codes problemlos als C++ kompilieren /
funktionieren würden, und man hätte die Chance, die kleinen "Goodies" zu
verwenden (wie hier etwa eine Klasse mit static-Elementen.
Schreibfaul wie ich bin, hätte ich mir ein locale.hc gebaut, und daraus
dann gawk ein locale.de.c und locale.h bauen lassen - inclusive dem
ganzen '#include'-, '#define'- und 'constflash char'-Gedöns. Ich hätte
mir sogar überlegt, ob ich die "Gänsefüßle" mir antun will.
1
// Fehlermeldung: EEPROM-Daten nicht richtig geschrieben
Statt '{}' kann man sich auch '[]' oder '<< >>' vorstellen.
Oder man bastelt da eine Sprachkennung mit rein, z.B.
1
LT_EEPROMWRITEFAILED
2
de{
3
" Fehler 0x%04x\n"
4
...
5
}
6
en{
7
" error 0x%04x\n"
8
...
9
}
10
is{
11
" villumelding ...
Weil ich ein Mega-Faultier bin, frickle ich für den gawk-Aufruf eine
extra Rule ins Makefile ...
gawk (früher hätte ich dazu lex und yacc bemüht) kann ich dir aber auf
die Schnelle nicht beibringen.
https://www.gnu.org/software/gawk/manual/gawk.pdf vermittelt aber einen
sehr guten Start.
just my 2ct
Walter T. schrieb:> Wilhelm M. schrieb:>> Warum erstellst Du nicht einfach ein Zugriffsfunktion?>> Welchen Vorteil habe ich dadurch?
Na, den Vorteil von jeder Indirektion: Du kannst weitere Erfordernisse
in der Funktion berücksichtigen, ohne etwas an der Aufrufstelle ändern
zu müssen. Du kannst bspw. dort eine Spracheinstellung berücksichtigen.
Man könnte auch alle Texte dort definieren, wo man sie braucht. Hier mal
ein Beispiel, wo ich das c11 _Generic Feature verwende, und die Sprache
per Macro setze. Der Compiler muss das dann im compile step auflösen.
Wenn die Sprache fehlt, bricht er ab, und gibt an, wo es fehlt. Und
falls man doch mal alle Sprachen zur Runtime brauchen sollte, kann man
einfach das Macro anpassen.
Und als kleiner Bonus, bei Format Strings in printf, mit eingestellten
Warnungen, warnt er sogar, wenn da was nicht passt!
https://godbolt.org/z/3crY18zT6
1
#ifndef LANG
2
#error "Please set the language using the LANG macro!"
Walter T. schrieb:> Gibt es eine Möglichkeit, die Konstanten (Deklarationen und> Definitionen) mit Bordmitteln an einer Stelle zu pflegen
Du solltest eine Lösung implementieren,
wo die Texte ÜBERHAUPT NICHT über den Compiler laufen!
Eine simple Textdatei, wo jeder Textstring mit einer Kennung (Nummer)
versehen wird.
Beispiel:
001:Messung läuft
002:Bitte warten
003:Abbruch!
004:usw.
Diese Textdatei wird dann auf eine feste "gerade" Adresse im
Speicherbereich einkopiert, z.B. 0x8000 . Tool z.B. SRecord
Deinem Compiler bzw. Linker mußt du beibringen, wo die Startadresse und
(maximale) Größe des Textes ist (aufrunden z.B. auf volle 16k).
Somit wäre in diesem Beispiel der Textbereich 0x8000 ... 0xBFFF
Musst eben passende Stelle für deinen uC finden.
In der SW brauchst du dann eine Textausgabefunktion mit den Parametern
- Zeile am Display zur Anzeige des Textes
- Spalte am Display zur Anzeige des Textes
- Textnummer Nummer des auszugebenden Textes
also z.B. Display(10,1,002) schreibe "Bitte warten" in Zeile 10,
Spalte 1
Die Funktion Display(..) muß dann die Kennung des Textes Nr. 002 im
Speicher finden anhand seines dort befindlichen Headers "002:"
Weiter ist nötig, das jeweilige Textende zu finden. Entweder ist das das
<CR><LF> Zeichen welches automatisch vorhanden ist. Oder man führt ein
definiertes Endezeichen zu jedem Text dazu, ein Zeichen das niemals
benötigt wird. Z.B. das "\"
002: Bitte warten \
Hoffe diese Ausführungen helfen.
Hatte mal ein Industrie-Meßgerät betreut, da gab es 14 Sprachvarianten.
Fremdsprachenkundige Sekrätarin konnte die Textdatei(en) nach Vorlage
editieren.
Gruss
Walter T. schrieb:> Es wird wohl> ein unerfüllter Traum bleiben.
Hannes hat einen Einzeiler dazu gepostet.
Hannes J. schrieb:> sed -e '1i\#ifndef X_H_\n#define X_H_' -e '/^$/d; s/^/extern /; s/> *=.*/;/' -e '$a\#endif' x.c
Ob er klappt, weiß ich nicht, aber mehr braucht es nicht. Ich nutze awk
(genauer mawk) für sowas, ist ähnlich. Einmal in "Regulare Expressions"
einarbeiten und schon hat man einen Textfresser mit dem man gerade für C
wirklich tolle Sachen machen kann (die in C++ nativ gehen aber nicht
einfacher sind).
Einfach per batch, makefile oder manuell per Kommandozeile. Kein "file
öffnen und lesen und interpretieren" sondern viele Kommandos zum
Ersetzen oder Verarbeiten von Zeichenketten oder durch Leerzeichen
getrennte Worte/Zahlen
Aufruf mit der Quelldatei (x.c) und umleitung (>) in die Zieldatei (x.h)
A. S. schrieb:> Walter T. schrieb:>> Es wird wohl>> ein unerfüllter Traum bleiben.>> Hannes hat einen Einzeiler dazu gepostet.
Das ist nicht das Problem.
Man will doch (natürlich) die .H-Datei eher halbautomatisch erstellen,
d.h. die Deklarationen von nicht-static-Funktionen und -Variablen sollte
automatisch erstellt (und bereinigt werden, wenn etwas verschwindet),
andererseit gibt es natürlich auch immer noch Aspekte der Schnittstelle,
die man händisch anpassen will, z.B. #includes oder Präprozessor Makros.
Aber auch das wäre vermutlich gar kein so großes Problem in Python oder
so selbst zu schreiben.
Das Problem ist, dass ich das Plugin-Konzept meiner IDE (EmBitz) nicht
verstehe, weil ich dazu keine Doku finde.
Aber vielleich wird das auch "blos" ein Rechtsklick-Tool für den
normalen Dateimanager, nicht für die IDE. Mal sehen. Vielleicht habe ich
nächste Woche mal Langeweile.
Walter T. schrieb:> A. S. schrieb:>> Walter T. schrieb:>>> Es wird wohl>>> ein unerfüllter Traum bleiben.>>>> Hannes hat einen Einzeiler dazu gepostet.>> Das ist nicht das Problem.
Brauchst Du doch gar nicht.
> Das Problem ist, dass ich das Plugin-Konzept meiner IDE (EmBitz) nicht> verstehe, weil ich dazu keine Doku finde.
make
Der Vorteil bei Verwendung von eigenen Makefiles ist, dass die
verwendete IDE dann egal ist, man kann sie sogar weg lassen, wenn man
will. Und man kann es machen & generieren lassen, was auch immer man
will.
Wilhelm M. schrieb:> Doch grundsätzlich stimme ich Dir natürlich zu und vertrete das ja hier> im Forum auch immer vehement, wofür ich ja dann auch mein Fett weg> bekomme ;-)
Jetzt höre doch mal auf zu jammern!
Ich vertrete hier eine ähnliche Linie wie du, nämlich: Bevorzuge C++.
Bekomme ich hier Haue dafür?
Nein! (eher nein, als ja)
Nee, du bekommst hier gerne mal Haue, weil du dich manchmal wie ein
arroganter Pinsel benimmst. Damit gehst du einigen auf den Keks. Auch
mir.
Und jetzt bist du sogar auch noch ein jammernder Pinsel....
Merke:
Kompetenz ist nicht alles!
EAF schrieb:> Wilhelm M. schrieb:>> Doch grundsätzlich stimme ich Dir natürlich zu und vertrete das ja hier>> im Forum auch immer vehement, wofür ich ja dann auch mein Fett weg>> bekomme ;-)>> Jetzt höre doch mal auf zu jammern!
Du siehst den Smiley, oder?
Also: nix jammern.
Und: negative Bewertung nicht vergessen ;-)
Wilhelm M. schrieb:> negative Bewertung nicht vergessen
Schon wieder am jammern!
Da gibts nichts zu vergessen!
Als Gast sehe ich weder Bewertungen, noch kann ich welche abgeben!
EAF schrieb:> Wilhelm M. schrieb:>> negative Bewertung nicht vergessen> Schon wieder am jammern!
Du hast den Smiley schon wieder übersehen und wohl auch absichtlich
nicht in die Zitatzeile übernommen.
Wilhelm M. schrieb:> Du hast ....
Es hört gar nicht auf mit dem jammern....
Ein Tipp (Gruppendynamik):
Wenn man seine Weltanschauung auf andere projiziert, werden die anderen
darauf reagieren. Allerdings nicht immer so, wie man sich das wünscht.
Und wer jammert, macht sich so selber zu einem Backpfeifengesicht.
EAF schrieb:> Wilhelm M. schrieb:>> Du hast ....>> Ein Tipp (Gruppendynamik):> Wenn man seine Weltanschauung auf andere projiziert, werden die anderen> darauf reagieren. Allerdings nicht immer so, wie man sich das wünscht.
Weltanschauung? Du scheinst Dich ja ziemlich angegriffen zu fühlen, wenn
jemand einfach feststellt, dass Du nicht zitieren kannst bzw. willst.
Wahrscheinlich auch ein Grund dafür, dass Du hier nur als Gast
schreibst.
Wilhelm M. schrieb:> Weltanschauung?
Naja, deine Beiträge zu C++ und zukünftigen Standards tragen schon stark
religiöse Züge in sich, inklusive des "ignorieren wir die Realität".
Zumindest oft genug, dass ich technische C++-Beiträge (also Code) von
dir inzwischen grundsätzlich ignoriere. War für mich noch nie sinnvoll
anwendbar.
GCC hatte lange die hässliche Eigenart mehrfach Deklarationen in
Headerfiles zu tolerieren. D.h. ein 'int something' konnte per header in
mehreren Modulen angelegt werden und es war trotzdem eine globale
Variable. Erst ab GCC10 gibt es Mecker vom Linker.
J. S. schrieb:> GCC hatte lange die hässliche Eigenart mehrfach Deklarationen in> Headerfiles zu tolerieren. D.h. ein 'int something' konnte per header in> mehreren Modulen angelegt werden und es war trotzdem eine globale> Variable. Erst ab GCC10 gibt es Mecker vom Linker.
Das ist normal und nennt sich "tentative definition", also eine
Defintion ohne Initialisierung. Die kann / darf zusammen gefasst werden.
Da das eben viele so nicht wissen, hat gcc dafür einen Schalter.
Nur das es jetzt als Fehler bewertet wird und das vorherige Verhalten
als Sonderfall, was dann Änderungen im Code oder Compilereinstellungen
nötig macht.
https://gcc.gnu.org/gcc-10/porting_to.html
J. S. schrieb:> Nur das es jetzt als Fehler bewertet wird und das vorherige Verhalten> als Sonderfall, was dann Änderungen im Code oder Compilereinstellungen> nötig macht.> https://gcc.gnu.org/gcc-10/porting_to.html
Naja, die "tentative definitions" waren schon immer so, nur die meisten
haben es nicht gewusst. Ein steter Quell von Fragen, daher dann die
Änderung des Verhaltens des gcc.
J. S. schrieb:> GCC hatte lange die hässliche Eigenart mehrfach Deklarationen in> Headerfiles zu tolerieren.
Ist explizit im Standard als eine von zwei Implementierungsmöglichkeiten
genannt worden. War wohl historisch so üblich, daher hat GCC das auch
lange Zeit als Default gehabt.
Die Option dazu ist -fcommon (bzw. -fno-common).
Neuere GCC-Versionen haben die Voreinstellung von -fcommon auf
-fno-common geändert.
Jörg W. schrieb:> J. S. schrieb:>> GCC hatte lange die hässliche Eigenart mehrfach Deklarationen in>> Headerfiles zu tolerieren.>> Ist explizit im Standard als eine von zwei Implementierungsmöglichkeiten> genannt worden. War wohl historisch so üblich, daher hat GCC das auch> lange Zeit als Default gehabt.
s.a. oben:
Beitrag "Re: Konstanten-Datei in C"
Walter T. schrieb:> Man will doch (natürlich) die .H-Datei eher halbautomatisch erstellen,> d.h. die Deklarationen von nicht-static-Funktionen und -Variablen sollte> automatisch erstellt (und bereinigt werden, wenn etwas verschwindet),> andererseit gibt es natürlich auch immer noch Aspekte der Schnittstelle,> die man händisch anpassen will, z.B. #includes oder Präprozessor Makros.
Das ist nicht wirklich ein Problem. Höchstens der Sprung ins kalte
Wasser.
* Es reicht ein Einzeiler.
* automatischer Aufruf ist immer machbar. Die Wege sind nur
verschieden.
* Die erzeugte .h selber braucht keine #include-guards etc. Das kann
eine "Wrapper".h leisten. Oder speziell gekennzeichnete Bereiche in der
.c, je nach Textfresser. Oder Du machst aus dem Einzeiler einen
Dreizeiler.
Wenn Du bei C bleiben willst (und das ist völlig OK, zumindest mache ich
das auch), dann hast Du mit Textfressern viele Möglichkeiten, die Dir
sauberen/lesbaren C-Code erlauben der Wartbar bleibt (Wartbar =
Änderungen nur an einer Stelle)
A. S. schrieb:> Walter T. schrieb:>> Man will doch (natürlich) die .H-Datei eher halbautomatisch erstellen,>> d.h. die Deklarationen von nicht-static-Funktionen und -Variablen sollte>> automatisch erstellt (und bereinigt werden, wenn etwas verschwindet)> Wenn Du bei C bleiben willst (und das ist völlig OK, zumindest mache ich> das auch), dann hast Du mit Textfressern viele Möglichkeiten, die Dir> sauberen/lesbaren C-Code erlauben der Wartbar bleibt (Wartbar => Änderungen nur an einer Stelle)
Das hatte ich ihm vor Tagen schon nahe gelegt:
Jester schrieb:> Pflege das [in] ein EINE .def/.hc/.irgendwas ein - aus der du> per Script .h und .c erzeugst (z.B. per awk, m4, ...).> Rule in's Makefile rein und fertig.
Und später noch mal (sogar mit Beispiel und opt. Unterstützung von
Multi-lingualität):
Jester schrieb:> Schreibfaul wie ich bin, hätte ich mir ein locale.hc gebaut, und daraus> dann gawk ein locale.de.c und locale.h bauen lassen> [...]> Weil ich ein Mega-Faultier bin, frickle ich für den gawk-Aufruf eine> extra Rule ins Makefile ...
Du hattest es ihm dann auch noch mal schmackhaft gemacht:
A. S. schrieb:> Ich nutze awk (genauer mawk) für sowas, ist ähnlich. Einmal in> "Regulare Expressions" einarbeiten und schon hat man einen Textfresser> mit dem man gerade für C wirklich tolle Sachen machen kann.
'Textfresser' wie awk will der Walter aber offensichtlich nicht.
Jester schrieb:> just my 2ct
So - aber nun bin ich wirklich raus!