Kann mir jemand erklären, wieso mir Schmierzeichen ausgegeben werden (C++)?

2 Antworten

Das Wort Schmierzeichen war mir bisher unbekannt. Ist das ein Dialekt? Darf ich mal fragen aus welchem Land und welcher Region du ungefähr kommst? In meiner Gegend kennt diesen Begriff vermutlich kaum jemand. :)

Zu deiner Frage: Eine Variable vom Typ "Zeiger auf char" wird von den Standard-Ein- und Ausgabe-Streams besonders behandelt, nämlich als sog. C-String.

Beispiel:

#include <iostream>

int main(void) {
  using namespace std;

  int i = 123;
  int * ip = &i;

  cout << "i: " << i << endl;
  cout << "ip: " << ip << endl;

  char c = 'x';
  char * pc = &c;

  cout << "c: " << c << endl;
  cout << "pc: " << pc << endl;

  const char * cstr = "Hallo!";
  cout << cstr << endl;
}

Wie du siehst, wird ein Integer als Zahl ausgegeben, und bei einem Zeiger darauf die Adresse des Zeigers.

Bei einem char wird ebenfalls der char direkt ausgegeben, aber bei einem Zeiger auf char erwartet der Compiler, dass es ein Zeiger auf einen Nullterminierten Speicherbereich ist, wobei alle Zeichen vor der Null ausgegeben werden.

Der Zeiger "cstr" am Ende zeigt auf das erste Zeichen der Zeichenkette "Hallo!", also auf das 'H'. Am Ende der Zeichenkette steht implizit ein Nullzeichen nach dem Ausrufezeichen, woran der Ausgabeoperator << erkennt, dass heir das Ende der Ausgabe erreicht ist ... er gibt also nur alle Zeichen vom ersten 'H' bis zum Ausrufezeichen am Ende aus und merkt dann sofort, dass Schluss ist.

Wenn du jetzt einem char-Zeiger, die Adresse einer einzelne char-Variablen zuweist, denkt der Ausgabestrom immer noch, dass es sich um einen nullterminierten C-String handelt, und gibt nicht nur das Zeichen aus, auf dass der Zeiger zeigt, sondern auch alle folgenden Zeichen, bis er über ein Nullzeichen stolpert, welches er für das Ende des C-Strings hält.

Dabei kann es je nach Compiler, Einstellungen und Plattformen passieren, dass dir das Programm entweder abstürzt, oder wirre "Schmierzeichen" in der Ausgabe erscheinen.

Alles in allem wird damit aber auf undefinierte Speicherbereiche zugegriffen, weshalb es sich um einen Programmierfehler handelt. Genau diese Art von Programmierfehlern kann man übrigens in Form von Sicherheitslücken ausnutzen, um Schabernack zu treiben, aber das hat jetzt nichts mit der Frage an sich zu tun ...

Wenn du die Adresse von einem char-Zeiger, wie die von einem int-Zeiger, als solche ausgeben willst, dann kannst du einen Cast nach void * nutzen:

cout << static_cast<const void *>(cstr) << endl;

Falls du das alles noch nicht richtig verstehst, lerne einfach immer schön weiter ... irgendwann wird dir das alles sowieso klar werden! :)


xBlackMass 
Beitragsersteller
 07.09.2018, 12:30

Danke dir :) Aber wieso denkt der Ausgabestrom das es sich immer noch um einen nullterminierten C-String handelt? Also was genau passiert intern?

p.s komme aus bayern :)

1
PeanutsButter  07.09.2018, 18:10
@xBlackMass

Das ist einfach Absicht, basierend auf der historisch gewachsenen Konvention, dass C-Strings nullterminierte Speicherbereiche sind.

Deshalb gibt es extra für diesen Fall eine Überladung des Ausgabeoperators ... alle anderen Zeiger werden als Adressen dargestellt, aber nur ein char-Zeiger wird speziell als C-String behandelt.

Viele Bibliotheken handhaben char-Zeiger auf diese Art und Weise, nicht nur die STL von C++.

Aber wenn du dir für irgend etwas deine eigene Bibliothek schreibst, kannst du dir natürlich aussuchen, ob du char-Zeiger gesondert behandeln willst, oder wie jeden anderen Zeigertyp auch. :)

1
Mikkey  07.09.2018, 18:12
@xBlackMass

Der Operator << ist für einen Stream (links) und einen char* (rechts) halt so definiert. Ein Computer denkt nicht, er tut, was man ihm sagt.

1

Schmierzeichen, wieder ein neues Wort gelernt ^^

Du gibst pVariable aus, und das ist ja ein Pointer auf deinen char buchstabe. Deshalb wird dir eben diese virtuelle Adresse der Variablen angezeigt. Sinnvoller wäre vielleicht:

count << *pVariable;
Woher ich das weiß:Hobby – Poweruser mit dem Bestreben, jedes System auszureizen