Welche Stringinitialisierung besser

lionq

Grünschnabel
hi
:confused:

Welches Programmstück würden Sie für die Ausgabe des Zeichenstrongs bevorzugen und warum?
C++:
	a:	char s[]="ABCDEFG";
		printf("%s", s);

	b:	char s[]={'A','B','C','D','E','F','G'};
		printf("%s",s);
bin mir nicht sicher aber würde ich a wählen aber ich kann ja nicht begründen,warum a die Antwort auf der Frage ist.........
 
Zuletzt bearbeitet:
Hi

a

In ein Array kann man grundsätzlich ja mehrere Werte einer Variablenart speichern.
Ganz frei alle verfügbaren Elemente mit irgendwelchen Werten belegen.

Dabei kann man aber nicht prüfen, wie voll das Array ist
bzw. ob ein Element schon einen eigenen Wert hat
(irgendein Wert steht von Anfang an immer drin,
Man weiß nicht, ob jetzt der Anfangswert noch drin ist
oder der Wert von einem selbst reingespeichert wurde.)

Bei zB. int-Arrays hilft man sich zB. damit, noch eine einzelne int-Variable zu machen
und da die Anzahl der belegten Elemente reinzuspeichern
(solange man immer die ersten x Elemente belegt hat und den Rest nicht.
Wenn man es irgendwie durcheinander hat braucht man eine andere Methode).

Auf char-Arrays trifft die Vorgehensweise prinzipiell auch zu.
Also ein Zahl, wie voll es ist oder so.

Es gibt aber eine Art stille Abmachung, das Ende des vollen Bereichs bei char-Arrays
mit einem speziellen Wert im letzten char zu markieren.
Deswegen muss man zB. bei der Ausgabe nicht angeben,
wieviel Buchstaben ausgegeben werden sollen.
printf gibt einfach soviel aus, bis es zum Endzeichen kommt.
Oder wenn man mit strcpy einen neuen Inhalt zuweist
wird von strcpy selbst das Endzeichen drangehängt.

Was das alles mit deiner Frage zu tun hat:
Bei a kommt der Inhalt mit Endzeichen in s rein.
Bei b wird kein Endzeichen dazugemacht.
->Bei der Ausgabe hört printf nicht nach dem G auf.

PS: Und bitte etwas aussagekräftigere Titel wählen als "c".
 
ich finde,dass deine Antworten klar und deutlich sind,die man sofort versteht..danke
noch NE FRAGE wollte ich mal wissen,ob das stimmt was ich geschrieben habe...?
C++:
list[]={1,2,3,4,5,6,7};//die Länge der Liste ist 7
list[5]={1,2,3}//die länge ist 5 erste 3 sind 123 dann kommt 2 Nullen  oder?
bei einer liste fängt immer mit 0 an,wenn es keine Initialisierung gibt

außerdem kannst du mit einem Bespiel Array und pointer erklären
mfg
 
Zuletzt bearbeitet:
Hallo lionq,

wenn du bei C++ die Array-Größe festlegst (hier via [5]) und Werte angibst, welche aber nicht die Länge abdecken, werden die restlichen Elemente mit der Zahl 0 befüllt.

Die Bezeichnung Liste hast du hier ein wenig ungünstig gewählt. In C++ meinen sie Double-Linked-Lists, sprich doppelt-verkettete Listen.

Die Zählung fängt bei Arrays allgemein immer mit 0 an.


Eine Array-Variable (list) ist nichts anderes als ein Pointer zum ersten Element.

Genauer:
Normalerweise wird vom Compiler aus eine implicit conversion ausgeführt, wenn du ein Array im Sinne eines Pointers (z.B. list[0]) nutzt.

Allerdings wird dies z.B. beim Adress-Operator unterbunden (&list), denn dort wird dann ein ein Typ von "pointer to array of T" rauskommen.
C++:
// Beides das selbe
int list[] = {1,2,3};

int *pList = new int[3];
pList[0] = 1;
pList[1] = 2;
pList[2] = 3;
Beachten musst du allerdings, dass ersteres ein Pointer zu einer Read-Only-Section in deinem Programm ist.
 
list[]={1,2,3,4,5,6,7};
Genau, das hat Länge 7
Weil man bei 0 zu zählen anfangt, von liste[0] bis liste[6] sind 7 Stück.
Der Wert in liste[0] ist 1, liste[1] ist 2...liste[6] ist dann eben 7.
(Zu "liste": Eigentlich ist es ja ein Array. Eine Liste ist das Zeug mit next)

list[5]={1,2,3}
Hat 5 Elemente, davon 0, 1 und 2 belegt, genau.
Element 3 und 4 sind aber nicht unbedingt 0, sondern irgendein Wert.
Wenn man 0 drinhaben will muss man das extra reinschreiben.

Ok, lionq und Cromon haben recht :)
Es ist 0



Jede Variable muss ja irgendwo im Speicher sein.
Die ganzen möglichen Plätze für Variablen im Speicher sind durchnummeriert.
Wenn man jetzt also ein
C++:
int i;
i = 10;
hat könnte das i an Stelle 1288 sein, dort ist dann 10 gespeichert.
Wo die Variablen hinkommen bzw. wo noch unbenutzter Platz frei ist
wird vom Compiler/Betriebssystem verwaltet.
Da braucht man sich selbst keine Sorgen darum machen.

(Die Platznummern sind immer ganze positive Zahlen.
Immer int´s. Auch wenn dort floats oder sonst was gespeichert sind)

Man kann die Platznummer ("Adresse") im Programm herausfinden,
indem man ein & vor den Variablennamen schreibt.
C++:
printf("%d", i); //Gibt den Wert 10 aus
printf("%d", &i); //Gibt die Adresse 1288 aus


Ein Pointer ist jetzt eigentlich ein normales int, mit der Besonderheit,
dass es dazu gedacht ist, Speicheradressen als Wert zu haben.
Da Adressen aber nur normale int-mäßige Zahlen sind,
kann man den Pointer zunächst ganz normal als int verwenden:
C++:
int *p; //Beim Anlegen einen * als Kennzeichnung für "Pointer"
p = 9876; //Nur mal als Beispiel
printf("%d", p); //Gibt 9876 aus. Klar

Was den Pointer jetzt besonders macht:
Mit *p kann man auf den Wert zugreifen, der die Adresse im Pointer hat.
C++:
printf("%d", *p); //Gibt den Wert auf Adresse 9876 aus
//Weil 9876 ja der Wert von p ist

Man kann also irgendwelche Speicheradressen einfach als Zahl in p reingeben
und dann per *p auf den Wert dieser Adresse zugreifen.
(In der Praxis ist es problematisch, irgendwelche Adressen zu nehmen,
wenn man nicht weiß, was dort eigentlich ist.)

Um das int i von oben herzunehmen (Wert 10, Adresse 1288):
C++:
p = 1288; //könnte man machen
p= &i; //oder man holt sich die Adresse von i so

printf("%d", *p); //Gibt 10 aus. An Adresse 1288 ist ja der Zehner vom i
*p = 11; //Damit ist i jetzt 11
printf("%d", i); //11


Welche Pointerart man hat
C++:
int *pi;
float *pf;
char *pc;
...
hat keine Auswirkung darauf, dass die Adressenzahl drin immer ein int ist.
Der Unterschied ist, welche Varialenart man dort an dieser Adresse dann hat.


Wie Pointer jetzt mit Arrays zusammenhängen:
Die vielen Werte des Arrays sind im Speicher genau "hintereinander",
dh. wenn der erste Wert ([0]) auf Adresse 1200 ist sind die nächsten eben 1201, 1202...
C++:
int arr[10];
Angenommen, das geht von 1200 bis inklusive 1209
Das, was du da als arr im Programm hast ist dann "nur" ein Pointer auf das Startelement.
Also ein
C++:
int *arr;
arr = 1200;
(zusätzlich wird natürlich irgendwo festgemacht, dass die Adressen
1200 bis 1209 besetzt sind, nciht für neue Variablen frei).

Den ersten der 10 Werte (eigentlich arr[0]) bekommt man in der Pointervariante mit *arr
arr[1] wäre *(arr + 1). Also 1200+1=1201, davon der Inhalt
arr[7] ist *(arr + 7) ...

(arr[0] ist eigentlich nicht nur *arr, sondern *(arr+0)
Macht nur keinen Unterschied, ob 0 dazugerechnet wird.)

Und das arr[bla] im Code ist in Wirklichkeit nur eine Kurzschreibweise für *(arr + bla)
Wird ganz real vom Computer so gemacht.

Das ist übrigens auch der Grund, warum man bei den Arrayelementnummern bei 0 beginnt.
Das Startelement ist auf (Startadresse + 0)
 
Zuletzt bearbeitet:
Hallo sheel,

Bezüglich Initialisierung eines Arrays mit einem initializer mit weniger Elementen als Grösse des Arrays, hier was der Standard dazu sagt:
If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized.

Mit value-initialized ist folgendes gemeint:
To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called
(and the initialization is ill-formed if T has no accessible default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static data member and baseclass component of T is value-initialized;
96)
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized

Im Falle int sind also alle Elemente die nicht in der { } angegeben werden dann mit 0 initialisiert. Aus diesem Grund ist für POD-Typen ein memset in der Regel auch überflüssig und sie können direkt sauber initialisiert werden:
C++:
PODType value = { 0 };

Grüsse
Cromon
 
Welches Programmstück würden Sie für die Ausgabe des Zeichenstrings bevorzugen und warum?
C++:
	a:	char s[]="ABCDEFG";
		printf("%s", s);

	b:	char s[]={'A','B','C','D','E','F','G'};
		printf("%s",s);

Ich persönlich würde von Variante b abraten, da das Array so nicht Null-terminiert ist.
Meine favorisierte Methode ist folgende:
C++:
char *text = "Mein Text".
printf("%s", text);

An sich das Gleiche wie deine Variante a.


Gruß
Michael
 
Ich persönlich würde von Variante b abraten, da das Array so nicht Null-terminiert ist.
Meine favorisierte Methode ist folgende:
C++:
char *text = "Mein Text".
printf("%s", text);

An sich das Gleiche wie deine Variante a.
Das ist nicht korrekt.

Einmal wird ein Array angelegt und mit dem Wert des Strings initialisiert.

Du legst nur einen Zeiger auf den String an und initialisierst mit der Adresse des Strings.

Wie ComFreek schon sagte, fehlt da ein const, da Stringliterale konstant sind. Versuchst du den String zu ändern, wird das undefiniertes Verhalten zu Folge haben - vermutlich Programm-Absturz.
 

Neue Beiträge

Zurück