Unterschied const #define
-
Michael E. schrieb:
Wenn du C programmierst, nimm #define, weil C kein const kennt.
C kennt auch const!
-
#define ist richtig const. konstanter geht's nicht
-
net: In C++ ist trotzdem const vorzuziehen.
-
Warum denn?
-
Laut Scott Meyers: Effektiv C++ Programmieren 3. Auflage Lektion 1 soll man den Compiler gegenüber dem Präprozessor bevorzugen. Ein Nachteil von #define gegenüber const ist beispielsweise eine Fehlerbeschreibung:
#define foo1 1234.546 // ... #define foo20 563.18 // Hier ist ein Fehler: double bar = foo1 + foo20;
Bei der Fehlerbeschreibung bekomm ich die letzte Zeile aber leider nicht so schön angezeigt, da foo1 bis foo20 schon vom Präprozessor ersetzt wurden. Ich sehe nur:
double bar = 1234.546 + 563.18;
Man muss dann erst mal nachgucken, für was das steht, weil man die Zahlen vielleicht noch nie gesehen hat.
Ein weiterer Nachteil ist Typunsicherheit.
-
net schrieb:
#define ist richtig const. konstanter geht's nicht
Dann solltest du diesen Irrtum dem ANSI mitteilen, damit sie es im Standard korrigieren können
.
-
Michael E. schrieb:
Ein Nachteil von #define gegenüber const ist beispielsweise eine Fehlerbeschreibung
das ist doch gar nichts im verhältnis zu sowas
const int a = 20; *(int*)&a = 100;
mein alter gcc compiled das ohne mecker. aber von einer konstanten gibts doch keine adresse???
-
net schrieb:
mein alter gcc compiled das ohne mecker. aber von einer konstanten gibts doch keine adresse???
Liegt vielleicht daran, dass er ALT ist. Nimmt der Compiler das wirklich ganz ohne meckern? Ist da nicht noch zumindest eine Warnung? (Sind dazu auch alle eingeschalten?)
Warum sollte es von einer Konstanten keine Adresse geben??
Nach deiner Auffassung wäre das hier nicht möglich:char * text = "Das ist ein konstanter Text."; puts(text);
hans0815 schrieb:
Was ist schneller, was erzeugt mehr code und was bruaucht nahher mehr RAM?
Ich weiß es zwar nicht sicher, aber ich denke, dass const besser ist; #define dürfte höchstens genauso gut sein (wobei ich glaube, dass es im Endeffekt gleich bleibt).
Ich mach das immer so, dass ich bei C++-Programmen const verwende und bei C-Programmen #define.
-
AJ schrieb:
Warum sollte es von einer Konstanten keine Adresse geben??
Nach deiner Auffassung wäre das hier nicht möglich:char * text = "Das ist ein konstanter Text."; puts(text);
nee, das ist was ganz anderes. der string ist deshalb konstant, weil er in einem read-only bereich gespeichert wird (alles was irgendwo gespeichert wird, hat eine adresse). wenn man die zugriffsrechte dieses speicherbereichs ändern würde (falls er ncht im rom ist), könnte man den string durchaus verändern.
aber bei
#define TEXT "Das ist ein konstanter Text." puts(TEXT);
ist es unmöglich den string zur laufzeit zu manipulieren. überall wo TEXT erscheint wird unweigerlich "Das ist ein konstanter Text." eingesetzt. wenn das nicht konstant ist, dann garnix mehr.
'const' hingegen ist z.b. gut für sowas:
void f (const int a) { a = 123; // error } f(10);
das lässt sich nicht mit #define machen (dafür ist #define 'zu' konstant)
fazit: const und #define sind nicht beliebig austauschbar
btw: ist es überhaupt erlaubt (bei neueren compilern) bei
const int a = 557667;
von a die adresse zu bilden.
-
aber bei
#define TEXT "Das ist ein konstanter Text." puts(TEXT);
ist es unmöglich den string zur laufzeit zu manipulieren. überall wo TEXT erscheint wird unweigerlich "Das ist ein konstanter Text." eingesetzt. wenn das nicht konstant ist, dann garnix mehr.
const char * const foo = "Dies ist eine konstante Zeichenkette";
Da kannst du auch nichts mehr dran rumpfuschen.
btw: ist es überhaupt erlaubt (bei neueren compilern) bei
const int a = 557667;
von a die adresse zu bilden.
[EDIT] Hier stand Quark. Es geht aber trotzdem mit dem Code: [/EDIT]
const int *b = &a;
-
Michael E. schrieb:
btw: ist es überhaupt erlaubt (bei neueren compilern) bei
const int a = 557667;
von a die adresse zu bilden.
Ja, mit einem konstanten Zeiger:
const int *b = &a;
und warum geht das?
const int a = 12345; const int *c = &a; int *p = (int*)c;
gcc 3.3.1, ohne error, ohne warning
dann kann a ja nicht wirklich const sein
-
Das ist ein C-Cast. Ich find sowieso, dass man die verbieten sollte.
[EDIT] Hast du auch versucht, den Wert zu ändern?
-
Michael E. schrieb:
[EDIT] Hast du auch versucht, den Wert zu ändern?
ja, a ändert sich nicht.
aber was ist das denn für eine adresse? ich kann was reinschreiben und es auch wieder auslesen. komisch, komisch...
-
Kurz eine Frage.. Ich habe das schon öfters in Quellcodes gesehen, hier im Thread kommts auch vor:
b = (int)&a;
Aber was genau steht dann in b? Eine Adresse bestimmt, aber was für eine? Und wozu braucht man sowas?
-
net schrieb:
Michael E. schrieb:
[EDIT] Hast du auch versucht, den Wert zu ändern?
ja, a ändert sich nicht.
Na also, es ist doch konstant. Was willst du mehr?
-
Michael E. schrieb:
Na also, es ist doch konstant. Was willst du mehr?
siehe oben. die adresse ist ja wohl eine andere, sonst würde sich a verändern. aber wo kommt die her?
-
net schrieb:
nee, das ist was ganz anderes. der string ist deshalb konstant, weil er in einem read-only bereich gespeichert wird (alles was irgendwo gespeichert wird, hat eine adresse). wenn man die zugriffsrechte dieses speicherbereichs ändern würde (falls er ncht im rom ist), könnte man den string durchaus verändern.
Nein, im Standard steht nichts von Read-Only-Bereichen oder sowas, Du hast keine Garantie dafür, daß etwas funktioniert, wenn Du in text rumpfuschst. Da "könnte man den String durchaus verändern" ist durch nichts abgedeckt.
aber bei
#define TEXT "Das ist ein konstanter Text." puts(TEXT);
ist es unmöglich den string zur laufzeit zu manipulieren. überall wo TEXT erscheint wird unweigerlich "Das ist ein konstanter Text." eingesetzt. wenn das nicht konstant ist, dann garnix mehr.
Das hat nichts mit konstant zu tun, sondern damit, daß eine Textersetzung vor dem Compilieren durchgeführt wurde. Streiche den Zusammenhang von define und Konstanten aus deinem Gedächtnis. Überlege dir, wie konstant
#define KONST rand()
ist.
btw: ist es überhaupt erlaubt (bei neueren compilern) bei
const int a = 557667;
von a die adresse zu bilden.
Ja.
Brutus schrieb:
b = (int)&a;
Aber was genau steht dann in b? Eine Adresse bestimmt, aber was für eine? Und wozu braucht man sowas?
Nein, da steht keine Adresse, sondern man interpretiert das Bitmuster, was an der Adresse von a steht, jetzt als Integer und speichert dieses Resultat in b. Das ist idR eine Bitschubssache, die exakte Kentnisse des Problems und des Systems erfordert, weil sowas nicht immer funktionieren muß ...
-
Daniel E. schrieb:
net schrieb:
nee, das ist was ganz anderes. der string ist deshalb konstant, weil er in einem read-only bereich gespeichert wird (alles was irgendwo gespeichert wird, hat eine adresse). wenn man die zugriffsrechte dieses speicherbereichs ändern würde (falls er ncht im rom ist), könnte man den string durchaus verändern.
Nein, im Standard steht nichts von Read-Only-Bereichen oder sowas, Du hast keine Garantie dafür, daß etwas funktioniert, wenn Du in text rumpfuschst. Da "könnte man den String durchaus verändern" ist durch nichts abgedeckt.
ok, ich bezog mich auch nicht auf die standards sondern darauf, was die mir bekannten compiler so machen
Daniel E. schrieb:
aber bei
#define TEXT "Das ist ein konstanter Text." puts(TEXT);
ist es unmöglich den string zur laufzeit zu manipulieren. überall wo TEXT erscheint wird unweigerlich "Das ist ein konstanter Text." eingesetzt. wenn das nicht konstant ist, dann garnix mehr.
Das hat nichts mit konstant zu tun, sondern damit, daß eine Textersetzung vor dem Compilieren durchgeführt wurde.
es gibt meiner meinung nach nichts konstanteres als eine textersetzung mit hilfe von '#define irgendwas konstanter_ausdruck'. da lässt sich zur laufzeit nichts mehr dran rütteln. das ding hat keine adresse, man kann es durch type-cast nicht variabel machen usw.
Daniel E. schrieb:
Überlege dir, wie konstant
#define KONST rand()
ist.
sicher, das ist aber was ganz anderes. zwar auch eine textersetzung aber mit #define lässt sich ja mehr machen als nur konstantem zu definieren
Daniel E. schrieb:
btw: ist es überhaupt erlaubt (bei neueren compilern) bei
const int a = 557667;
von a die adresse zu bilden.
Ja.
aber was hat es für einen sinn wenn man das 'const' über umwege wegcasten kann?
-
net schrieb:
nee, das ist was ganz anderes. der string ist deshalb konstant, weil er in einem read-only bereich gespeichert wird (alles was irgendwo gespeichert wird, hat eine adresse).
Richtig der Text wird wo gespeichert und hat damit eine Adresse. Meinst du das ist bei "konstanten" Ausdrücken im Quellcode nicht der Fall?
Denn nichts anderes ist dein Makro:#define TEXT "Das ist ein konstanter Text." puts(TEXT);
ist es unmöglich den string zur laufzeit zu manipulieren. überall wo TEXT erscheint wird unweigerlich "Das ist ein konstanter Text." eingesetzt. wenn das nicht konstant ist, dann garnix mehr.
Wie du ja schön berschreibst, überall wo TEXT steht, steht dann beim Compilieren "Das ist ein konstanter Text.", also:
puts("Das ist ein konstanter Text.");
Und was spricht jetzt dagegen, so vorzugehen?
char * text = TEXT;
Hoppla, da hat ja dein absolut "konstanter" Ausdruck doch wieder eine Adresse.
-
net schrieb:
aber was hat es für einen sinn wenn man das 'const' über umwege wegcasten kann?
Was für einen Sinn haben Haustüren, wenn die Einbrecher sie aufbrechen können?
Const bietet, wie Bjarne Stroustrup sagen würde, Schutz gegen Zufälle aber nicht gegen Betrug.
Du darfst das const nicht wegcasten, sofern das dahinterliegende Objekt wirklich als const definiert ist.
void f(const char *p) { *(char*)p = 'a'; } void g(void) { const char c = 'c'; char d = 'd'; f(&d); /* legal */ f(&c); /* undefiniertes Verhalten */ }