Warum benötigt const char * keinen Zeiger auf eine Speicheradresse?

18

Dies mag eine einfache Frage sein, aber warum benötigt ein const char * keine Speicheradresse, auf die es verweisen kann?

Beispiel:

const char* a = "Anthony";

und nicht:

const char *a = // Address to const char

wie alle anderen Typen?

Weidelix
quelle
8
Was lässt Sie denken, dass String-Literale keine Speicheradressen haben?
user207421
2
Einverstanden. Ich würde nicht erwarten, dass jemand, der diese Frage stellt, überhaupt weiß, dass Wertkategorien existieren, geschweige denn, dass sie Namen haben.
user4581301
13
Bitte stellen Sie keine mit C und C ++ gekennzeichneten Fragen. Wie wir beobachten können, sind die Antworten jetzt C ++ - spezifisch und die Kommentare über die Unterschiede zwischen beiden Sprachen entgleisen erneut. Mittlerweile gibt es so viele Unterschiede, dass es schwierig ist, eine Frage zu stellen, die für beide Sprachen dieselbe gültige Antwort hat. Entscheiden Sie bitte, welche Sprache Sie verwenden möchten, bevor Sie fragen.
Larkey

Antworten:

26

Sie können sich diese Erklärung vorstellen

const char* a = "Anthony";

der folgende Weg

const char string_literal[] = "Anthony";

const char *a = string_literal;

Das heißt, der Compiler erstellt ein Array von Zeichen mit der statischen Speicherdauer, in der die Zeichenfolge gespeichert ist, "Anthony"und die Adresse des ersten Zeichens des Arrays (aufgrund der impliziten Konvertierung von Array-Bezeichnern in Zeiger auf ihre ersten Zeichen) wird dem Zeiger zugewiesen a.

Hier ist ein Demonstrationsprogramm, das zeigt, dass Zeichenfolgenliterale Zeichenarrays sind.

#include <iostream>
#include <type_traits>

decltype( auto ) f()
{
    return ( "Anthony" );
}

template <size_t N>
void g( const char ( &s )[N] )
{
    std::cout << s << '\n';
}

int main() 
{
    decltype( auto ) r = f();

    std::cout << "The size of the referenced array is "
              << std::extent<std::remove_reference<decltype( r )>::type>::value
              << '\n';

    g( r );

    return 0;
}

Die Programmausgabe ist

The size of the referenced array is 8
Anthony

Die Größe des Zeichenfolgenliteral (des Arrays, in dem das Zeichenfolgenliteral gespeichert ist) ist gleich, 8da die Zeichenfolge auch das abschließende Nullzeichen 'enthält \0'.

Im Demonstrationsprogramm der Ausdruck

std::extent<std::remove_reference<decltype( r )>::type>::value

kann nur für den Ausdruck ersetzt werden

sizeof( r )
Vlad aus Moskau
quelle
5

Warum benötigt ein const char keine Speicheradresse, auf die er verweisen kann? *

Es tut.

Ein C-String-Literal wie

"Anthony"

wird an die Adresse seines 1 abgeklungen st Charakter. Wie übrigens; Jedes Array in C tut dies.

alk
quelle
Insbesondere ist es vom Typ const char[8](in C ++ möglicherweise char [8]in C, nicht sicher) und wie alle integrierten Arrays, wenn es als Wert verwendet wird, zerfällt es in einen Zeiger auf sein erstes Element.
Nikos C.
@NikosC.: Danke, dass du mich an das wichtigste magische Verb in diesem Zusammenhang erinnert hast! ;)
alk
Danke für die Antwort! Ich habe mich gefragt, woher es die Erinnerung hat.
Weidelix
1
Ich kann nicht für C sprechen, aber ich bin mir ziemlich sicher, dass C ++ nicht angibt, wo ein Sting-Literal gespeichert werden muss. Ging einfach graben. Wenn es eine Regel gibt, ist sie irgendwo begraben und weit entfernt von jeglicher Erwähnung von "String-Literal".
user4581301
2
@ NikosC. char [8]in C: c-faq.com/ansi/strlitnotconst.html
David Ranieri
1

Es benötigt eine Speicheradresse und es hat eine Speicheradresse. In Ihrem Beispiel ist es einfach die Speicheradresse am Anfang der Zeichenfolge. Dies gilt auch für alle anderen Array-Variablen, die zur Kompilierungszeit initialisiert werden, z. B. "int array [] = {0, 1, 2, 3};".

Wenn Sie einen binären Editor verwenden, um die ausführbare Datei anzuzeigen, wird dort die Zeichenfolge "Anthony" angezeigt. Wenn Sie die Zeile "printf (" a steht bei% p \ n ", (void *) a);" Wenn Sie es in Ihrem Programm kompilieren und ausführen, wird die Adresse angezeigt.

jamesqf
quelle
0

"Warum braucht const char*man keinen Zeiger auf eine Speicheradresse?"

In der Tat, es hat eine Speicheradresse zu Punkt müssen.

const char* ameans aist ein Zeiger auf ein String-Literal oder eine Zeichenkonstante.

Ein Zeiger benötigt immer eine Adresse, auf die er zeigen muss, da es die Natur eines Zeigers ist, auf ein bestimmtes Objekt im Speicher zu zeigen. Also, aund jeder andere Zeiger auf const chartut es auch.

Ein String-Literal wie "Hi My Name is Alfred!"durch eine Zuweisung wie:

const char* a;
a = "Hi My Name is Alfred!";

zerfällt in einen Zeiger auf die Adresse des ersten Elements des String-Literal.

Bedeutet wiederum, awird durch die Adresse des ersten Elements des Zeichenfolgenliteral zugewiesen, das "Hi My Name is Alfred!"abhängig von der Ausführungsumgebung an einer beliebigen Stelle im Speicher gespeichert werden kann.

Es liegt nicht in der Macht eines Programmierers, wo ein String-Literal genau gespeichert ist. Ihre Aufgabe besteht nur darin, den jeweiligen Zeiger entsprechend zuzuweisen und zu behandeln.

RobertS unterstützt Monica Cellio
quelle