¿Por qué const char * no necesita un puntero a una dirección de memoria?

18

Esta puede ser una pregunta simple, pero ¿por qué un const char * no necesita una dirección de memoria para señalar?

Ejemplo:

const char* a = "Anthony";

y no:

const char *a = // Address to const char

como cualquier otro tipo de hacer?

Weidelix
fuente
8
¿Qué te hace pensar que los literales de cadena no tienen direcciones de memoria?
user207421
2
Convenido. No esperaría que alguien que haga esta pregunta sepa siquiera que existen categorías de valores , y mucho menos que tengan nombres.
user4581301
13
No haga preguntas etiquetadas con C y C ++. Como podemos observar, las respuestas ahora son específicas de C ++ y los comentarios descarrilan nuevamente sobre las diferencias entre ambos lenguajes. Hay tantas diferencias en este momento que es difícil hacer una pregunta que realmente tenga la misma respuesta válida para ambos idiomas. Decide qué idioma quieres usar antes de preguntar, por favor.
larkey

Respuestas:

26

Puedes imaginar esta declaración

const char* a = "Anthony";

de la siguiente manera

const char string_literal[] = "Anthony";

const char *a = string_literal;

Es decir, el compilador crea una matriz de caracteres con la duración de almacenamiento estático que almacena la cadena "Anthony"y la dirección del primer carácter de la matriz (debido a la conversión implícita de designadores de matriz a punteros a sus primeros caracteres) se asigna al puntero a.

Aquí hay un programa demostrativo que muestra que los literales de cadena son matrices de caracteres.

#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 salida del programa es

The size of the referenced array is 8
Anthony

El tamaño del literal de cadena (de la matriz que almacena el literal de cadena) es igual a 8porque la cadena incluye también el carácter de terminación cero ' \0'.

En el programa demostrativo la expresión

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

puede ser sustituido solo por la expresión

sizeof( r )
Vlad de Moscú
fuente
5

¿Por qué un const char no necesita una dirección de memoria para señalar? *

Lo hace.

Un literal C-string como

"Anthony"

se descompone a la dirección de su 1er carácter. Me gusta, por cierto; cualquier matriz en C lo hace.

alk
fuente
Más específicamente, es de tipo const char[8](en C ++, podría estar char [8]en C, no estoy seguro) y, al igual que todas las matrices integradas, cuando se usa como un valor se desintegra en un puntero a su primer elemento.
Nikos C.
@NikosC .: ¡Gracias por recordarme el verbo mágico más importante en este contexto! ;)
alk
¡Gracias por la respuesta! Me preguntaba de dónde saca el recuerdo.
Weidelix
1
No puedo hablar por C, pero estoy bastante seguro de que C ++ no especifica dónde debe almacenarse un literal de picadura. Solo fui a cavar. Si hay una regla, está enterrada en algún lugar extraño y lejos de cualquier mención de "cadena literal".
user4581301
2
@NikosC. char [8]en C: c-faq.com/ansi/strlitnotconst.html
David Ranieri
1

Necesita una dirección de memoria, y TIENE una dirección de memoria. En su ejemplo, es simplemente la dirección de memoria del comienzo de la cadena. Es lo mismo con cualquier otra variable de matriz que se inicializa en tiempo de compilación, por ejemplo "int array [] = {0, 1, 2, 3};".

Si usaras un editor binario para mirar el ejecutable, verías la cadena "Anthony" allí. Si coloca la línea "printf (" a está en% p \ n ", (void *) a);" en su programa, luego compílelo y ejecútelo, verá la dirección.

jamesqf
fuente
0

"¿Por const char*qué no necesita un puntero a una dirección de memoria?"

De hecho, se hace necesario una dirección de memoria a punto de hacerlo.

const char* asignifica aes un puntero a una cadena literal o constante de caracteres.

Un puntero siempre requiere una dirección para apuntar porque es la naturaleza de un puntero apuntar a un objeto específico en la memoria. Entonces, ay cualquier otro puntero const chartambién lo hace.

Una cadena literal como "Hi My Name is Alfred!"por una tarea como:

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

decae a un puntero a la dirección del primer elemento de la cadena literal.

Significa, a su vez, que ase asigna por la dirección del primer elemento del literal de cadena "Hi My Name is Alfred!"que podría almacenarse en cualquier lugar de la memoria dependiendo del entorno de ejecución.

No está en el poder de un programador donde un literal de cadena se almacena exactamente. Su tarea es solo asignar y manejar el puntero correspondiente de manera apropiada.

RobertS apoya a Monica Cellio
fuente