Pourquoi const char * n'a-t-il pas besoin d'un pointeur vers une adresse mémoire?

18

Cela peut être une question simple, mais pourquoi un caractère const * n'a-t-il pas besoin d'une adresse mémoire vers laquelle pointer?

Exemple:

const char* a = "Anthony";

et pas:

const char *a = // Address to const char

comme tous les autres types?

Weidelix
la source
8
Qu'est-ce qui vous fait penser que les littéraux de chaîne n'ont pas d'adresse mémoire?
user207421
2
D'accord. Je ne m'attendrais pas à ce que quiconque pose cette question sache même qu'il existe des catégories de valeurs , et encore moins qu'elles ont des noms.
user4581301
13
Veuillez ne pas poser de questions étiquetées avec C et C ++. Comme nous pouvons le constater, les réponses sont désormais spécifiques au C ++ et les commentaires déraillent à nouveau sur les différences entre les deux langages. Il y a tellement de différences maintenant qu'il est difficile de poser une question qui a en fait la même réponse valide pour les deux langues. Décidez quelle langue vous souhaitez utiliser avant de demander, s'il vous plaît.
larkey

Réponses:

26

Vous pouvez imaginer cette déclaration

const char* a = "Anthony";

de la manière suivante

const char string_literal[] = "Anthony";

const char *a = string_literal;

Autrement dit, le compilateur crée un tableau de caractères avec la durée de stockage statique qui stocke la chaîne "Anthony"et l'adresse du premier caractère du tableau (en raison de la conversion implicite des désignateurs de tableau en pointeurs vers leurs premiers caractères) est affectée au pointeur a.

Voici un programme démonstratif qui montre que les littéraux de chaîne sont des tableaux de caractères.

#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;
}

La sortie du programme est

The size of the referenced array is 8
Anthony

La taille du littéral de chaîne (du tableau qui stocke le littéral de chaîne) est égale à 8car la chaîne inclut également le caractère zéro de fin ' \0'.

Dans le programme démonstratif, l'expression

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

peut remplacer seulement l'expression

sizeof( r )
Vlad de Moscou
la source
5

pourquoi un caractère const n'a- t-il pas besoin d'une adresse mémoire vers laquelle pointer? *

Cela fait.

Un littéral de chaîne C comme

"Anthony"

est décomposé à l'adresse de son 1 er caractère. Comme, BTW; tout tableau en C le fait.

alk
la source
Plus précisément, il est de type const char[8](en C ++, peut-être char [8]en C, pas sûr) et comme tous les tableaux intégrés, lorsqu'il l'utilise comme valeur, il se désintègre en un pointeur sur son premier élément.
Nikos C.
@NikosC .: Merci de me rappeler le verbe magique le plus important dans ce contexte! ;)
alk
Merci d'avoir répondu! Je me demandais d'où venait cette mémoire.
Weidelix
1
Je ne peux pas parler pour C, mais je suis presque sûr que C ++ ne spécifie pas où un littéral sting doit être stocké. Je suis juste allé creuser. S'il y a une règle, elle est enterrée dans un endroit étrange et loin de toute mention de "chaîne littérale".
user4581301
2
@NikosC. char [8]dans C: c-faq.com/ansi/strlitnotconst.html
David Ranieri
1

Il a besoin d'une adresse mémoire et il a une adresse mémoire. Dans votre exemple, c'est simplement l'adresse mémoire du début de la chaîne. C'est la même chose avec toute autre variable de tableau qui est initialisée au moment de la compilation, par exemple "int array [] = {0, 1, 2, 3};".

Si vous utilisiez un éditeur binaire pour regarder l'exécutable, vous verriez la chaîne "Anthony" là-dedans. Si vous mettez la ligne "printf (" a est à% p \ n ", (void *) a);" dans votre programme, puis compilez-le et exécutez-le, vous verrez l'adresse.

jamesqf
la source
0

"Pourquoi n'a const char*- t -il pas besoin d'un pointeur vers une adresse mémoire?"

En fait, il ne faut une adresse mémoire pour pointer vers.

const char* asignifie aun pointeur vers un littéral de chaîne ou une constante de caractère.

Un pointeur nécessite toujours une adresse vers laquelle pointer car c'est la nature d'un pointeur de pointer vers un objet spécifique en mémoire. Donc, aet tout autre pointeur vers le const charfait aussi.

Un littéral de chaîne comme "Hi My Name is Alfred!"par une affectation comme:

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

se désintègre en un pointeur sur l'adresse du premier élément du littéral de chaîne.

Signifie à son tour, aest attribué par l'adresse du premier élément de la chaîne littérale "Hi My Name is Alfred!"qui pourrait être stockée n'importe où dans la mémoire en fonction de l'environnement d'exécution.

Ce n'est pas dans la puissance d'un programmeur où un littéral de chaîne est exactement stocké. Votre affectation consiste uniquement à affecter et à gérer le pointeur respectif de manière appropriée.

RobertS soutient Monica Cellio
la source