unterschied zwischen char* x="bla" und char x[]="bla"
-
char* x="bla"; //(1) char x[]="bla"; //(2)Was ist jetzt eigentlich der Unterschied zwischen den beiden Zeichenketten? Ich schätze mal das bei bei dem ersten ein char Zeiger angelegt wird, der auf eine Art Zeichenkettenkonstante zeigt. Beim zweiten handelt es sich afaik um ein char Array mit konstanter länge. Mein Beispielprogramm stürzt nämlich ab, sobald ich versuche zwei Zeichenketten wie bei (1) zu vertauschen.
void swap(char* eins, char* zwei) { char h; size_t l = strlen(eins); for(size_t i = 0; i < l; i++) { h = eins[i]; eins[i] = zwei[i]; // absturz wenn "eins" und "zwei" vom Typ: char* var = "wert" zwei[i] = h; } } int main(int argc, _TCHAR* argv[]) { char w1[] = "meins",w2[] = "deins"; char *str1 = "Eins", *str2 = "Zwei"; swap(w1,w2); // geht swap(str1, str2); // geht nicht return 0; }Edit: wie kann man dann char *str1 = "" Zeichenketten vertauschen? Das ganze wird von einer Übungsaufgabe aus einem Buch vorgegeben. Eigentlich wollte ich die nur mal aus Spaß durchmachen... hätte nicht gedacht das ich bei sowas nicht mehr weiterkomme.
-
Chris++ schrieb:
char* x="bla"; //(1) char x[]="bla"; //(2)Was ist jetzt eigentlich der Unterschied zwischen den beiden Zeichenketten? Ich schätze mal das bei bei dem ersten ein char Zeiger angelegt wird, der auf eine Art Zeichenkettenkonstante zeigt. Beim zweiten handelt es sich afaik um ein char Array mit konstanter länge. Mein Beispielprogramm stürzt nämlich ab, sobald ich versuche zwei Zeichenketten wie bei (1) zu vertauschen.
Meines Erachtens ist der Unterschied, dass Fall (1) nur ein Zeiger auf ein Zeichenliteral ist, welches dann in „globalem“ Speicher liegt (z.B. eine TEXT-Komponente der Binärdatei), in Fall (2) aber tatsächlich die Zeichenkette auf dem Stack liegt, also in lokalem Speicher vorhanden ist.
(1) solltest du daher auf keinen Fall verändern (ich bin mir nicht sicher, warum das überhaupt erlaubt ist, vielleicht weil altes C kein const kennt?).
-
.filmor schrieb:
(1) solltest du daher auf keinen Fall verändern (ich bin mir nicht sicher, warum das überhaupt erlaubt ist, vielleicht weil altes C kein const kennt?).
Ne das ist schon c++. Hab oben noch reineditiert das es sich hierbei um eine Übungsaufgabe aus einem Buch handelt (C++, UML und Design Patterns, Addison-Wesley). Vorgabe war das 2 Zeichenketten (wie bei (1)) mit echtem Call-by-Reference vertasucht werden.
-
mit char *p = "foobar" erzeugst du einen pointer, der auf einen const "string" zeigt. der darf nicht verändert werden, weshalb dir dein programm um die ohren fliegt, wenn du es versuchst.
-
Dann geht das wahrscheinlich wirklich nur in C und es ist eine kleine Falle in der Übungsaufgabe.
-
Chris++ schrieb:
Dann geht das wahrscheinlich wirklich nur in C und es ist eine kleine Falle in der Übungsaufgabe.
Nein, auch in C geht das nicht.
-
der compiler kann beim übersetzen nicht feststellen, dass da bockmist fabriziert wird
die signatur der funktion ist mit dem aufruf vereinbar, weshalb es durchgeht. aber beim ausführen knallts dann.
-
Nicht, dass das wer falsch versteht (auch wenn es dafür höchstvermutlich schon zu spät ist ;)), ich meinte tatsächlich fragend, warum Stringliterale (die ja const char[n] laut Standard sind) sich mit einem einfachen char* bezeigen lassen und hatte das wiederum fragend auf früheres C zurückgeführt, welches noch kein const hatte. Gibt's auf diese Fragen Antworten?
-
.filmor schrieb:
Gibt's auf diese Fragen Antworten?
In der Tat gab es in C im K&R-Stil das Schlüsselwort const nicht (ich würde das gerne durch einen Standard belegen, jedoch bin ich mir nichtmal sicher, ob K&R ein Standard war). Den Rest kann ich nur vermuten, nämlich dass genau aus Kompatiblitätsgründen Stringliterale heute noch char* sein können.
Im C++-Standard steht in 2.13.4.1, dass Stringliterale den Typ "Array von const char" haben, und ich finde gerade auch keine Ausnahme für die Konvertierung nach non-const. Andererseits hat nichtmal der Comeau-Compiler etwas dagegen, daher gibt es hier auch noch Klärungsbedarf

-
Es tritt faszinierenderweise nur bei Stringliteralen auf. Versucht man das gleiche mit einem normalen const char-Array gibt's einen Compilerfehler.
-
ISO/IEC 14882:2003 schrieb:
4.2 Array-to-pointer conversion [conv.array]
...
2 A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to char”; a wide string literal can be converted to an rvalue of type “pointer to wchar_t”. In either case, the result is a pointer to the first element of the array. This conversion is considered only when there is an explicit appropriate pointer target type, and not when there is a general need to convert from an lvalue to an rvalue. [Note: this conversion is deprecated. See Annex D. ] For the purpose of ranking in overload resolution (13.3.3.1.1), this conversion is considered an array-to-pointer conversion followed by a qualification conversion (4.4). [Example: "abc" is converted to “pointer to const char” as an array-to-pointer conversion, and then to “pointer to char” as a qualification conversion. ]
-
Danke.