Speichern einer Zeichenfolge in einem Zeichenfeld ohne das Nullzeichen

Ich lese den C ++ Primer Plus von Stephen Prata. Er gibt dieses Beispiel:

char dog[8] = { 'b', 'e', 'a', 'u', 'x', ' ', 'I', 'I'}; // not a string!
char cat[8] = {'f', 'a', 't', 'e', 's', 's', 'a', '\0'}; // a string!

mit dem Kommentar, dass:

Beide Arrays sind Zeichen-Arrays, aber nur das zweite ist ein String. Das Null-Zeichen spielt eine grundlegende Rolle in Strings im C-Stil. Beispielsweise verfügt C ++ über viele Funktionen, die Zeichenfolgen verarbeiten, einschließlich der von cout verwendeten. Sie alle verarbeiten Zeichenfolgen zeichenweise, bis sie das Nullzeichen erreichen. Wenn Sie cout auffordern, eine nette Zeichenfolge wie cat im vorherigen Beispiel anzuzeigen, werden die ersten sieben Zeichen angezeigt, das Nullzeichen wird erkannt und die Wiedergabe wird angehalten. Wenn Sie jedoch nicht freundlich genug sind, cout anzuweisen, das Hundearray aus dem vorhergehenden Beispiel anzuzeigen, das kein String ist, druckt cout die acht Buchstaben des Arrays und wandert dann byteweise durch den Speicher, wobei jedes Byte als a interpretiert wird Zeichen zu drucken, bis es ein Nullzeichen erreicht. Da Nullzeichen, bei denen es sich eigentlich um auf Null gesetzte Bytes handelt, im Arbeitsspeicher häufig vorkommen, ist der Schaden normalerweise schnell behoben. Nichtsdestotrotz sollten Sie Nicht-String-Zeichen-Arrays nicht als Strings behandeln.

Wenn Sie nun meine Variablen global deklarieren, gehen Sie wie folgt vor:

#include <iostream>
using namespace std;

char a[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
char b[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};

int main(void)
{
    cout << a << endl;
    cout << b << endl;

    return 0;
}

die Ausgabe wird sein:

abcdefgh12345678
12345678

Der cout "durchläuft den Speicher in der Tat fortlaufend byteweise", jedoch nur bis zum Ende des zweiten Zeichenarrays. Dasselbe passiert mit jeder Kombination von char-Arrays. Ich denke, dass alle anderen Adressen auf 0 initialisiert sind und deshalb die Cout zu stoppen. Ist das wahr? Wenn ich etwas mache wie:

for (int i = 0; i < 100; ++i)
{
    cout << *(&a + i) << endl;
}

Ich erhalte am Ausgang größtenteils leeren Speicherplatz (etwa 95%), aber nicht überall.

Wenn ich jedoch meine char-Arrays etwas kürzer deklariere, wie:

char a[3] = {'a', 'b', 'c'};
char b[3] = {'1', '2', '3'};

Wenn alle anderen Dinge gleich bleiben, erhalte ich die folgende Ausgabe:

abc
123

Jetzt kommt der Cout nicht einmal an dem ersten Char-Array vorbei, ganz zu schweigen von dem zweiten. Warum passiert dies? Ich habe die Speicheradressen überprüft und sie sind sequentiell, genau wie im ersten Szenario. Zum Beispiel,

cout << &a << endl;
cout << &b << endl;

gibt

003B903C
003B9040

Warum ist das Verhalten in diesem Fall anders? Warum liest es nicht über das erste Zeichen-Array hinaus?

Und schließlich, wenn ich meine Variablen in main deklariere, erhalte ich das von Prata vorgeschlagene Verhalten, nämlich, dass viel Müll gedruckt wird, bevor irgendwo ein Null-Zeichen erreicht wird.

Ich vermute, dass im ersten Fall das char-Array auf dem Heap deklariert wird und dass dieses auf 0 initialisiert wird (aber nicht überall, warum?) Und cout sich basierend auf der Länge des char-Arrays anders verhält (warum?).

Ich verwende Visual Studio 2010 für diese Beispiele.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage