Arrayinitialisierung nur per define möglich
-
char *p="12345";
funzt,
char p[4] = "123456";
haut Dir das Programm zusammen bzw. ergibt schwer zu findende Probleme.
Ob da eine "4" oder eine Konstante per #define drinne steht ist egal.
Der Präprozessor ersetzt im Quelltext und nicht zur Laufzeit.[code]#define HEPP 4
char p[HEPP] ="...";[quote]ist absolut identisch mit
[code]char p[4] ="...";[quote]
-
dust schrieb:
RICHTIG, da steht der WERT 5, aber eben NUR dort und nicht noch am ***** irgendwo ... einmal weniger halt ...
EDIT: GO 4 Seite5 ^^
-
OK, es besteht die Möglichkeit, dass ich falsch liege, aber ist es nicht so, dass bei einer nicht durch "#define" definierten Konstante der Wert (hier:5) einmal sinnlos irgendwo im Code (bei Code rede ich vom "Maschinencode" oder meinetwegen auch von Assembler) steht? Und genau dieses eine mal ist halt mehr als bei #define ... ist immernoch net klar, was ich meine? Als nächstes mal ich ein Bild .. xD ..
-
dust schrieb:
OK, es besteht die Möglichkeit, dass ich falsch liege, aber ist es nicht so, dass bei einer nicht durch "#define" definierten Konstante der Wert (hier:5) einmal sinnlos irgendwo im Code (bei Code rede ich vom "Maschinencode" oder meinetwegen auch von Assembler) steht? Und genau dieses eine mal ist halt mehr als bei #define ... ist immernoch net klar, was ich meine? Als nächstes mal ich ein Bild .. xD ..
Falsch.
Wenn man einen Gammel-Compiler hat, und ein DEFINE an N Stellen benutzt, dann bekommt man dadurch N Ersetzungen und der ersetzte Wert wird N mal in den Maschinencode gepackt.
Ein const hingegen steht an einer dedizierten Speicherzelle und muss so nur einmal vorhanden sein. Gute Compiler sollten aber Defines auch dahin gehend auflösen können (glaube ich, bin mir nicht sicher).
-
Aber einen Wert reinzupacken (auch, wenn es N mal ist) ist noch immernoch effizienter und weniger aufwändig, als jedesmal eine Adresse reinzupacken, die dann jedesmal angesprungen werden muss. Das meine ich, und ich denke jetzt versteht es auch jeder.
-
Tachyon schrieb:
Ehem, und dann kommt im Code ja noch meist sowas:
int cnt; for(cnt = 0; cnt < SIZE; ++cnt) { /*...*/ }
So, und was passiert? Richtig. SIZE wird durch den Wert 5 ersetzt. Und diese 5 wird zu einem Bestandteil Deines Kompilates und steht irgendwo im Speicher. Oder wo soll er die Deiner Meinung nach her nehmen? Zur Laufzeit gibts keinen Präprozessor.
nicht zwansgläufig. Manche Optimierungsstufen wie -funroll-loops können dazu führen, dass der Inhalt der for-Schleife eben 5 Mal hintereinander vorkommt. Dann muss im Code keine 5 für die Abbruchbedingung auftauchen
Um ehrlich zu sein, verstehe ich gar nicht mehr, worüber ihr euch letzendlich streitet. Ein #define ist eine reine Textersetzung vor der Compilieren. Ob die integralen Konsanten hinter dem define vom Compiler zur echten Konstanten werden oder nicht, hängt ihmo vom Kontext ab, wo das Makro auftaucht (und eben welche Optimierungsstufe man wählt).
Tachyon schrieb:
Gute Compiler sollten aber Defines auch dahin gehend auflösen können (glaube ich, bin mir nicht sicher).
was soll das genau heißen?
-
Streiten würd ich das jetzt nicht nennen, wir sind ja friedlich und wollen am Ende nur mit bestem Wissen und Gewissen aus der Diskussion rausgehen. Ich hab' schonwieder ein bisschen dazu gelernt, und am Ende werde ich genau wissen, wann ich welche Konstante (bzw. Konstantendefinition) weswegen nehmen kann und nehmen sollte, darum gehts.
-
dust schrieb:
Bei #define SIZE 5 ersetzt der Preprozessor wie gesagt die entsprechenden Stellen (SIZE durch 5), die 5 taucht im Code der "EXE" und damit auch im Arbeitsspeicher (bei Ausführung) nicht auf. Das Array wird die Länge 5 haben und fertig. Andernfalls (nicht #define) ist die Länge ebenfalls klar, aber die 5 ist zusätzlich und völlig unnütz auch noch im Code und bei Ausführung im ProcessMemory oder wo auch immer vorhanden.
Natürlich kommt die 5 irgend wo vor. Immerhin muss der Speicher ja nach bereit gestellt werden und dazu sollte man die Länge wissen.
-
Bei #define SIZE 5 ersetzt der Preprozessor wie gesagt die entsprechenden Stellen (SIZE durch 5), die 5 taucht im Code der "EXE" und damit auch im Arbeitsspeicher (bei Ausführung) nicht auf. Das Array wird die Länge 5 haben und fertig. Andernfalls (nicht #define) ist die Länge ebenfalls klar, aber die 5 ist zusätzlich und völlig unnütz auch noch im Code und bei Ausführung im ProcessMemory oder wo auch immer vorhanden.
Natürlich kommt die 5 irgend wo vor. Immerhin muss der Speicher ja nach bereit gestellt werden und dazu sollte man die Länge wissen.
Das hatten wir schon klar gestellt, dachte ich ..
Aber einen Wert reinzupacken (auch, wenn es N mal ist) ist noch immernoch effizienter und weniger aufwändig, als jedesmal eine Adresse reinzupacken, die dann jedesmal angesprungen werden muss. Das meine ich, und ich denke jetzt versteht es auch jeder.
Für mich ist jetzt nur noch unklar ob bei Konstanten, die durch const definiert wurden, bei Benutzung jener immer an die Adresse gesprungen wird, wo der Wert steht, oder ob, wie bei einer durch #define definierten Konstanten, überall der Wert der Konstante steht. Wenn immer die Adresse angesprungen werden würde, dann wär da für mich ganz klar ein Vorteil von #define.
-
dust schrieb:
Für mich ist jetzt nur noch unklar ob bei Konstanten, die durch const definiert wurden, bei Benutzung jener immer an die Adresse gesprungen wird, wo der Wert steht, oder ob, wie bei einer durch #define definierten Konstanten, überall der Wert der Konstante steht. Wenn immer die Adresse angesprungen werden würde, dann wär da für mich ganz klar ein Vorteil von #define.
möglicherweise kann ein compiler eine const-variable wegoptimieren, so dass das gleiche rauskommt, wie bei einem define.
btw: verfechter von const-variablen pochen oft darauf, dass diese variablen eine typinformation haben, was ja bei einfachen defines nicht so ist (naja, nicht ganz, die sind, bei einfachen zahlen, vom typ 'int'). aber wenn man einen anderen typ als int braucht, kann man's mit define auch machen:#define CHARFOUR ((char)4)
ein nachteil von const-variablen ist z.b. dass man das 'const' wegcasten kann:
const int a = 0; *(int*)&a = 10; // compiliert zwar, aber ob das gut ist?
bei einem #define hat man mit solchen tricks keine chance
#define TRULY_CONST 123 TRULY_CONST = 10; // error *(int*)&TRULY_CONST = 10; // error
-
Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
Namens direkt in den Programmtext eingesetzt.#define HUHU das ist aber lustig
schreibt Dir nun mal anstelle des HUHU den Text ins Programm.
Man kann im Präprozessor auch prüfen, ob's das Ding gibt: #ifdef HUHU und #endif,
dazu noch ein Paar andere Möglichkeiten. Es ist etwas völlig anderes wie eine
Variablemdeklaration, es in eine Anweisung für den Präprozessor.
-
Scheppertreiber schrieb:
Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
Namens direkt in den Programmtext eingesetzt.richtig! aber genau das ist machmal ein vorteil.
-
fricky schrieb:
Scheppertreiber schrieb:
Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
Namens direkt in den Programmtext eingesetzt.richtig! aber genau das ist machmal ein vorteil.
Aber ja. Da soll der Compiler ja auch nichts optimieren.
So ein #ifdef DEBUG ist äußerst praktisch ...
-
Scheppertreiber schrieb:
fricky schrieb:
Scheppertreiber schrieb:
Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
Namens direkt in den Programmtext eingesetzt.richtig! aber genau das ist machmal ein vorteil.
Aber ja. Da soll der Compiler ja auch nichts optimieren.
wie sollen ihn #defines am optimieren hindern?
-
Der Compiler selbst dürfte ein #define nicht sehen. #define gehört nicht zum
Sprachumfang, genau wie #include etc. Es sind Anweisungen für den Präprozessor.Was er nicht sieht kann er nicht optimieren.
-
Scheppertreiber schrieb:
Der Compiler selbst dürfte ein #define nicht sehen...
Was er nicht sieht kann er nicht optimieren.er sieht aber den quelltext, auf den #defines direkte auswirkungen haben.
beispiel:#define HELLOTEXT "hello, world!" ... char *a = HELLOTEXT; char *b = HELLOTEXT; char *c = HELLOTEXT;
der compiler kann 'string pooling' anwenden, damit der initialisierer nur einmal im binary vorkommt.
-
Klar.
Würde ich so etwas in einem PIC8 verwenden würde ich auch viel Wert drauf legen
Für Windows ist das wurscht, da wird soviel mit Ressourcen geaast, da kommt's auf
die Paar Bytes nicht an.In Deinem Beispiel würde ich das von Haus aus schon so definieren:
char *p = "Hallo bin auch da";
printf( "\n%s", p);
printf( "\n%s", p);
...
-
Scheppertreiber schrieb:
Würde ich so etwas in einem PIC8 verwenden würde ich auch viel Wert drauf legen
Für Windows ist das wurscht, da wird soviel mit Ressourcen geaast, da kommt's auf
die Paar Bytes nicht an.deswegen nimmt unter windows heute noch kaum jemand C. dafür gibt's ja .NET und ähnliches. aber da, wo C oft verwendet wird, ist auch sehr oft resourcensparendes programmieren angesagt.
-
Es hat Gründe warum ich bei C bleibe:
Ich habe eine wilde Mischung aus CGI- Kommandozeilen und Windowsprogrammen (da
zum Glück aber nur wenige). Ich plane, das (wenn ich mal Zeit habe) auf Linux zu
portieren. Versuche habe ich gemacht, geht relativ problemlos.NET etc. werde ich nicht verwenden. Ich bin dann auch wieder zu Updates gezwungen
und das hänge ich mir nicht mehr ans Bein.C ist schnell, extrem flexibel und ich kann große System draus bauen. Der ++Overhead
erinnert mich zu stark an Deutsche Verwaltung und bringt mir nichts.
-
Scheppertreiber schrieb:
C ist schnell, extrem flexibel und ich kann große System draus bauen.
da hast du recht, aber das bauen von grossen systemen ist in C verdammt aufwendig und fehleranfällig, bereits eine kleine windows-anwendung mit fensterchen oder dialogboxen und graphischen controls usw. würde ich nicht in C machen wollen (auch wenn's dafür libraries wie GTK u.ä. gibt).
Scheppertreiber schrieb:
Der ++Overhead erinnert mich zu stark an Deutsche Verwaltung und bringt mir nichts.
meinst du C++? ja, das sind wir einer meinung. C++ finde ich auch total schrottig.