Zeiger und Vektoren
-
Genau...allerdings wird wenn ich cptr mit cout ausgebe trotzdem das komplette Wort ausgegeben.
Wenn ich einen normalen Zeiger vom Typ int mit einer Integer-Variablen intialisieren und dann ohne Anwendung
des Derenferenzierungsoperators (*) mit cout ausgebe (so wie in meinen Code-Beispiel) wird mir die
Adresse ausgegeben. Warum da die Adresse und bei Vektoren das ganze Objekt?
-
Weil
std::cout
für verschiedene Typen verschiedene Dinge tut. Ganz einfach. Wenn du eine Variable vom Typchar*
übergibst, dann weißcout
(bzw.operator<<
weiß), dass du einen nullterminierten String ausgeben willst. Bei anderen Pointer-Typen gibt es keine solche Spezialbehandlung und dann kommt eben die Adresse raus.Im Prinzip liegt es also daran, dass der
operator<<
vom ostream fürchar*
überladen ist. Siehe hier: https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2Man hat also einen Spezialfall, der sehr nützlich ist, eingebaut.
Edit: Bitte sprich lieber von einem Array, wenn du Arrays meinst. In C++ versteht man unter "Vector" eigentlich immer
std::vector
.
-
Alles klar...dann weis ich Becheid. Vielen Dank!
Im Kapitel Zeiger und Arrays habe ich allerdings eine weitere Funktion vor mir, bei mir ich nicht
verstehe was da gemacht wurde/wie das möglich ist:int strlen(char * str)
{
char * p = str;
for (p=str; *p != '\0'; ++p)
;
return (p -str)
}Warum wurde hier str ohne Verwendung des Adressoperators & den Zeiger p zugewiesen. Wären nicht
die beiden Varianten char* p = &str bzw. char *p = *str nur möglich?
Was drückt dann der Ausruck p=str bzw. ++p aus? Müsste nicht eigentlich der Verweisoperator * angewendet werden
wenn dort Werte zugewiesen werden bzw. in dem String weitergesprungen wird?
-
@C-Sepp hmm, steht in deinem Buch wirklich
int strlen(char * str)
?
Falls ja, würde ich das Lehrmaterial wechseln.size_t strlen(const char *str) { const char *p; for (p = str; *p; ++p) ; return (p - str); }
-
Innerhalb von strlen ist str eine lokale Zeiger-Variable.
Ebenso wie pBei &str bekommst du die Adresse, wo str selber liegt. dies wäre auch vom Typ char** (Ein Zeiger auf einen Zeiger auf char).
Mit *str bekommst du den Wert an der Stelle str. das wäre ein char.Beide Typen passen nicht zu p (was ja ein char* ist)
@C-Sepp sagte in Zeiger und Vektoren:
Was drückt dann der Ausruck p=str
Eine Zuweisung: p bekommt den Inhalt von str. Also die Adresse die in str abgelegt ist.
(ist hier überflüssig, da dies in der Zeile davor (Definition von *p mit Initialisierung) schon gemacht wird.bzw. ++p aus?
Das ist Pointer-Arithmetik. der Inhalt von p wird erhöht. p Zeigt jetzt auf das nächste Element.
Dabei wird die Größe von *ptr (hier char) berücksichtigt.p-str liefert die Differenz (Abstand) der Adressen.
Da p auf das Ende com String zeigt, bekommt man somit die Länge.
-
@DirkB sagte in Zeiger und Vektoren:
p-str liefert die Differenz (Abstand) der Adressen.
Um das noch zu präzisieren: es ist der Abstand in Einheiten der Größe des Typen, auf den man zeigt. Wenn du z.B. einen Pointer auf einen 32-bit Integer hast (und char 8 Bit hat), dann gehst du mit
int_pointer + 1
gleich 4 Bytes weiter, weil eben der Integer 4 Bytes groß ist. Würdest du den Pointer vorher nachchar*
casten und dann 1 addieren, würdest du noch "in der Mitte" des integers landen. Das heißt, die Differenz hängt von der Pointee-Größe ab. Oder anders: wenn der Typ korrekt ist, bekommst du mit*(pointer+1)
immer das nächstfolgende Element im Array.
-
Okay...das habe ich soweit verstanden.
Müsste im Programmbeispiel:double *pv, v[5] = {5.5,4.4,3.3,2.2,1.1}
for (pv = v+4; pv >=v; --p)
*pv *=2;Warum wird dann der Schleifenrumpf 5 mal durchlaufen?
Müsste es nicht nur viermal sein, dass heißvon 1.1 zu 2.2, 2.2 -> 3.3, 3.3 -> 4.4, 4.4 -> 5.5?
-
@C-Sepp sagte in Zeiger und Vektoren:
Warum wird dann der Schleifenrumpf 5 mal durchlaufen?
Weil bei pv == v (pv zeigt auf den Anfang vom Array) die Bedingung
pv >=v
noch wahr ist. Die Schleife wird dann nochmal ausgeführt.
-
@C-Sepp sagte in Zeiger und Vektoren:
double *pv, v[5] = {5.5,4.4,3.3,2.2,1.1}
for (pv = v+4; pv >=v; --p)
*pv *=2;
Warum wird dann der Schleifenrumpf 5 mal durchlaufen?Der Code funktionier gar nicht. Oder woher kommt "p"? Wenn du mit p pv meintest, dann verstehe ich dir Frage.
Müsste es nicht nur viermal sein, dass heißvon 1.1 zu 2.2, 2.2 -> 3.3, 3.3 -> 4.4, 4.4 -> 5.5?
Aber ich komme auf 5:
- v + 4
- v + 4 - 1
- v + 4 - 2
- v + 4 - 3
- v + 4 - 4
Ich weiß nicht so recht, was du mit "von 1.1 zu 2.2" etc. meinst. Es läuft der Pointer pv (=v + 4) herunter, solange der Wert >= v ist.
-
Ja genau mit p meinte ich pv. Sorry! Okay!!
-
Arbeite gerade die Thematik zu Zeiger und Arrays durch. Darin steht, dass der ++-Operator einen
höheren Vorrang als der Verweisoperator * hat, weshalb *pv++ mit *(pv++) äquivalent ist.
In dem Codebeispiel steht wiederrum:float v[6] = {0.0F, 0.1F, 0.2F, 0.3F, 0.F, 0.5F}, *pv, x;
pv= v+4;
pv -=2;
++pv;
x= *pv++; //v[3] an x zuweisen, dann pv ein Element weiterals Kommentar "v[3] an x zuweisen, dann pv ein Element weiter". Müsste es nach der oben aufgeführten Regel
nicht genau andersrum sein....sprich pv ein Element weiter, dann v[4] an x zuweisen? Vielen Dank!
-
@C-Sepp sagte in Zeiger und Vektoren:
Darin steht, dass der ++-Operator einen
höheren Vorrang als der Verweisoperator * hat, weshalb *pv++ mit *(pv++) äquivalent ist.Das bedeutet, dass du den Pointer nach dem Zugriff auf *p erhöhst.
(*pv)++ inkrementiert den Wert, auf den p zeigt. Du bekommst aber noch den Wert vor dem inkrement.
-
Okay...ich hätte erwartet, dass die Operation, welche einen höheren Vorrang hat, in Klammern gesetzt wird und
auch zuwerst ausgeführt wird. Irgendwie ein bisschen unlogisch
-
@C-Sepp sagte in Zeiger und Vektoren:
und
auch zuwerst ausgeführt wird.Du bekommst trotzdem den Pointer von vor dem Inkrement. Du denkst an *(++p)
-
Hallo Leute,
ich habe ein weiteres interssantes Codebeispiel gefunden , in dem sich eine Frage ergeben hat:
char arr[] = "open sea";
char* p = arr, * q = arr + 4; cout << q - p << endl; cout << *q << endl; p = ++q; while (p < q + 3) cout << *p++ << endl; cout << *q << endl; cout << *arr << endl; cout << *(q - 2) << endl; cout << *q << endl;
Ausgabe:
4s
e
s
o
n
sIch verstehen was das Programm gemacht hat, um auf dieses Ergebnis zu kommen. Jedoch verstehe
ich nicht, warum der Zeiger *q ab der While-Schleife auf das "s" im Array zeigt. Müsste er nicht auf
das Leerzeichen zwischen open und sea zeigen? Der zweite Ausgabewert ist ja ein Leerziechen.
Nochmals vielen Dank!
-
Entschuldige die Ausgabe ist:
4
s
e
a
s
o
n
s
-
Bei
p = ++q
wirdq
nebenher um 1 erhöht. Vorher standq
auf dem Leerzeichen, wie du mit der zweiten Ausgabe gesehen hast, danach eben eins weiter auf dem 's'.
-
Ahh okay...also wird mit p=++q auch q gleichzeitig um 1 erhöht. Vielen Dank!
-
Es wird zuerst q erhöht, und dieses Resultat, nach der Erhöhung, wird dann p zugewiesen.
Anders wäre es bei:p = q++;
Hier bekommt p den Wert von q, danach wird q inkrementiert.
Nach:p = ++q;
haben also p und q denselben Wert, nach:
p = q++;
nicht.
-
++q heißt Preinkrement, weil q erst erhöht wird und dann mit dem Wert gearbeitet wird.
q++ heißt Postinkrement, weil der Wert zuerst von q genommen wird und danach der Wert erhöht wird.
Das passiert aber auch nicht unbedingt unmittelbar nachdem der Wert genommen wurde.
p = q++ + q++;
ist z.B. undefiniertes Verhalten.