problemoSizeof schrieb:
> Kann man das erste Beispiel dem compiler irgend wie schmackhaft machen?
Nicht mit sizeof.
In diesem Fall musst du strlen benutzen, so wie bei jedem anderen
String, von dem du die Länge nicht kennst.
Oftmals kann man aber auch ganz einfach die Tatsache ausnutzen, dass das
letzte Byte des Strings '\0' enthält und seine Schleifen so formulieren,
dass man die Länge gar nicht braucht.
Anstelle von
problemoSizeof schrieb:
> also gibt die header datei mit>> extern const char msg [];>> die info für sizeof nicht her.
Nein.
sizeof wird zur Compiletime ausgewertet. Und genausowenig wie du bei
1
externconstcharmsg[];
die Länge weißt, genausowenig weiß sie auch der Compiler. Der kann ja
auch nicht zaubern :-)
Muss der string im .c-file sein? Im header wenn er ist gehts nämlich.
sizeof wird zur compile-Zeit ermittelt und darum muss der string dann
auch bekannt sein. Ist er aber nicht, da er nicht im header steht.
HTH,
Nick
Nick Müller schrieb:
> Muss der string im .c-file sein? Im header wenn er ist gehts nämlich.
Leider ist genau das das Problem
(Zumindest dann, wenn man nicht die gcc-Linker Erweiterung benutzen
will)
> Leider ist genau das das Problem
Ich versteh nicht, warum das so sein muss, ich kenn mich mit dem gcc
aber auch nicht aus.
Alternativ ginge es auch evtl. über ein #define Dann stehts aber auch
wieder im header.
Gruß,
Nick
Nick Müller schrieb:
>> Leider ist genau das das Problem>> Ich versteh nicht, warum das so sein muss, ich kenn mich mit dem gcc> aber auch nicht aus.
Das Problem ist, dass das hier
extern const char msg[] = "Hallo Welt";
keine Deklaration ist (wie man durch das extern meinen könnte) sondern
eine Definition. Durch die Initialisierung wird das extern ignoriert.
Gibt man obiges also in ein Header File, und inkludiert dieses in a-c
und in b.c, so hat man 2 Definitionen von msg im System. Nach dem
Buchstaben des Gesetzes ist das aber ein No-No.
> extern const char msg[] = "Hallo Welt";
Ja, natürlich gehts genau so nicht. Aber muss das denn extern sein?
Er will das Problem ja irgendwie gelöst haben.
Sorry für das Misverständnis. Ist mir schon klar, dass der string zur
compile-time vorliegen muss.
Gruß,
Nick
Nachtrag:
> Gibt man obiges also in ein Header File, und inkludiert dieses in a-c> und in b.c, so hat man 2 Definitionen von msg im System. Nach dem> Buchstaben des Gesetzes ist das aber ein No-No.
Naja, alter hut:
Header-file "foo.h":
1
#ifndef __FOO_H__
2
#define __FOO_H__
3
4
// was da rein soll
5
6
#endif
So werden multiple includes verhindert.
Gruß,
Nick
Nick Müller schrieb:
> Nachtrag:>>> Gibt man obiges also in ein Header File, und inkludiert dieses in a-c>> und in b.c, so hat man 2 Definitionen von msg im System. Nach dem>> Buchstaben des Gesetzes ist das aber ein No-No.>>> Naja, alter hut:>> Header-file "foo.h":>
1
>#ifndef__FOO_H__
2
>#define__FOO_H__
3
>
4
>// was da rein soll
5
>
6
>#endif
7
>
>> So werden multiple includes verhindert.
Die helfen dir in diesem Fall nicht :-)
Include Guards sind nur dann eine Hilfe, wenn dasselbe #include in einer
Compilation Unit auftaucht.
> Das ist zwar richtig, löst aber das Problem des Threadstarters nicht.
Natürlich löst es das Problem, ausser er besteht darauf es so zu machen
wie es nicht geht. :-)
Er könnte evtl. mal erklären, warum er den string unbedingt in den
implementation-file stecken will. Das ist nämlich ein Widerspruch:
Einesteils versteckt er ihn, anderenteils soll er von aussen zugänglich
sein. Also was nun?
Das "extern" ist sowieso eher ein 4-letter-word (mit 5 Buchstaben).
Gruß,
Nick
> Die helfen dir in diesem Fall nicht :-)
Dann muss ich zugeben, dass ich das Problem überhaupt nicht verstehe.
Ohne das "extern" und dem string in einem header:
Wie muss das aussehen, dass es nicht funktioniert?
MMn bringt man das immer zum compilieren. Ausser mit "extern", da sind
wir uns einig.
Gruß,
Nick
Nick Müller schrieb:
> Dann muss ich zugeben, dass ich das Problem überhaupt nicht verstehe.>> Ohne das "extern" und dem string in einem header:> Wie muss das aussehen, dass es nicht funktioniert?
msg.h
Nick Müller schrieb:
>> => msg im gesamten Programm 2 mal definiert.>> Wurde schon beantwortet, such mal hier nach "#ifndef".
Und es wurde ebenso schon beantwortet, dass dein Include-Guard dieses
Problem nicht löst.
Nick Müller schrieb:
>> => msg im gesamten Programm 2 mal definiert.>> Wurde schon beantwortet, such mal hier nach "#ifndef".
Dir scheint die Erkentniss zu fehlen, dass der Compiler, wenn er
datei_2.c compiliert, wieder bei 0 anfängt. Welche Erkentnisse oder
#define er beim compilieren von datei_1.c gewonnen hat, wird zu Schall
und Rauch sobald er sich datei_2.c vornimmt.
Und damit hilft dir zwar ein Include Guard wenn es darum geht mehrfache
Defintionen in datei_1.c zu bekämpfen. Aber sie helfen nicht Probleme zu
lösen, die dadurch entstehen, dass ein include File in datei_1.c UND
datei_2.c inkludiert wird. Aus Compilersicht haben die beiden nichts
miteinander zu tun. Insbesondere ist es völlig egal, welche #define beim
compilieren von datei_1.c gemacht wurden. Sobald der fopen für datei_2.c
erfolgt ist, sind die alle wieder verschwunden.
Es ist ein wesentliches Prinzip von C, dass jede *.c für sich alleine,
ohne Ansehen aller anderen *.c die zum Projekt gehören, compiliert wird.
> Und es wurde ebenso schon beantwortet, dass dein Include-Guard dieses> Problem nicht löst.
Dann bitte ich höflichst um ein Beispiel. Kann ja durchaus sein, dass
ich falsch liege. Dann möchte ich aber ungerne dumm sterben.
Gruß,
Nick
Hallo Danke an alle,
da habe ich ja was losgetreten.
Ich mache es jetzt über ein zusätzliches #define im header und zähle die
Zeichen.
Ich möchte die Ausgaben per Compilerschalter für verschiedene Sprachen
haben.
Die verwendeten Ausgabestrings sind jetzt über mehrere Dateien verteilt.
Um bei einer Änderung auf eine neue Sprache nicht wieder alle Files
durchsuchen zu müssen habe ich mich für den Weg mit einem extra c file
entschieden.
mfg
Vielleicht habe ich den Kick an dem Problem ja nicht mitbekommen, aber
zumindest das zählen kann der Präprozessor für Dich erledigen.
In einer H-Datei:
1
#define MSG "Dies ist eine Nachricht"
2
#define MSG_LENGTH (sizeof(MSG) - 1)
Stringliterale kann man mit sizeof nämlich schon zählen.
(Da gab es hier auch mal einen Thread).
Dann kannst Du in einer C-Datei auch:
Hallo nochmal,
ich glaube diese von Rufus t. Firefly vorgeschlagene lösung ist die
beste
So ließe sich das lösen:
// bla.c
const char msg[] = " Hallo";
const int size = sizeof(msg);
// bla.h
extern const char msg[];
extern const int size;
// main.c
#include "bla.h"
wasauchimmer(msg, size);
besten dank
Nick Müller schrieb:
> Zu meiner Erkentniserweiterung muss ich das wohl einfach ausprobieren.
Dann vergiss aber nicht, dem Linker ein "--warn-common" mitzugeben,
ansonsten schluckt er dieses "No-No" nämlichen kommentarlos (aus
historischen Gründen).
Oder alternativ (und vielleicht besser): dem Compiler die Option
-fno-common mitgeben.
> Dann vergiss aber nicht, dem Linker ein "--warn-common" mitzugeben,
Wie gesagt, ich kenn mich mit dem gcc nicht aus (hab ihn nicht mal), und
weiß daher auch nicht, was das --warn-common bewirkt.
Dass der string als symbol in beiden obj steht (aus a.c und b.c) ist
klar. MMn darf sich der linker daran aber nicht stören, denn erst zum
linken wird den symbols Speicherplatz zugewiesen und die Adressen darauf
im obj aufgelöst. Dass ein und das selbe symbol in mehreren objs
referenziert wird ist ja nur natürlich und kein Grund zum Meckern
solange das der gleiche typ ist.
Naja, ich probiers aus und schau mir den map-file an.
Entspannter Gruß!
Nick
Nick Müller schrieb:
> MMn darf sich der linker daran aber nicht stören, denn erst zum> linken wird den symbols Speicherplatz zugewiesen und die Adressen darauf> im obj aufgelöst. Dass ein und das selbe symbol in mehreren objs> referenziert wird ist ja nur natürlich und kein Grund zum Meckern> solange das der gleiche typ ist.
Es wird dann aber nicht nur das selbe Symbol referenziert, sondern auch
definiert. Das ist ja das, was nicht passieren darf und warum es das
"extern" auch überhaupt gibt.
Nick Müller schrieb:
> klar. MMn darf sich der linker daran aber nicht stören,
Doch, er darf.
> denn erst zum> linken wird den symbols Speicherplatz zugewiesen
Und der Linker findet in den einzelnen Object Files mehrere
Speicheranforderungen, die alle denselben Namen tragen. Und dann darf er
sich daran stören :-)
> im obj aufgelöst. Dass ein und das selbe symbol in mehreren objs> referenziert wird ist ja nur natürlich und kein Grund zum Meckern> solange das der gleiche typ ist.
Das sieht der C-Standard aber anders :-)
Aber wie gesagt: Im gcc Linker ist eine Erweiterung eingebaut, die so
etwas erlaubt.