Estoy ejecutando algunos programas de ejemplo para volver a familiarizarme con C ++ y me he encontrado con la siguiente pregunta. Primero, aquí está el código de ejemplo:
void print_string(const char * the_string)
{
cout << the_string << endl;
}
int main () {
print_string("What's up?");
}
En el código anterior, el parámetro de print_string podría haber sido const char * const the_string
. ¿Cuál sería más correcto para esto?
Entiendo que la diferencia es que uno es un puntero a un carácter constante, mientras que el otro es un puntero constante a un carácter constante. Pero, ¿por qué funcionan ambos? ¿Cuándo sería relevante?
const char *
es mucho mejor porqueconst
está en el lado completamente opuesto.Puntero mutable a un personaje mutable
Puntero mutable a un carácter constante
Puntero constante a un personaje mutable
Puntero constante a un carácter constante
fuente
const char* p; --> constant pointer to mutable character
ychar *const p; --> mutable pointer to constant character
const char * p
como: "p es un puntero a una constante de carácter" o un puntero mutable a un carácter constante, como James dice correctamente. lo mismo con el segundo :).const char * const
medios puntero, así como los datos del puntero apuntada, son tanto const!const char *
significa que solo los datos a los que apunta el puntero son constantes. sin embargo, el puntero en sí no es constante.Ejemplo.
fuente
(Sé que esto es antiguo, pero quería compartirlo de todos modos).
Solo quería desarrollar la respuesta de Thomas Matthews. La regla derecha-izquierda de las declaraciones de tipo C dice más o menos: cuando lea una declaración de tipo C, comience en el identificador y vaya a la derecha cuando pueda y a la izquierda cuando no pueda.
Esto se explica mejor con un par de ejemplos:
Ejemplo 1
Comience en el identificador, no podemos ir a la derecha, así que vamos a la izquierda
foo es una constante ...
Continuar a la izquierda
foo es un puntero constante a ...
Continuar a la izquierda
foo es un puntero constante a char ...
Continuar a la izquierda
foo es un puntero constante a char constante (¡Completo!)
Ejemplo 2
Comience en el identificador, no podemos ir a la derecha, así que vamos a la izquierda
foo es una constante ...
Continuar a la izquierda
foo es un puntero constante a ...
Continuar a la izquierda
foo es un puntero constante a char (¡Completo!)
Ejemplo 1337
Empiece por el identificador, ¡pero ahora podemos ir a la derecha!
foo es una matriz de 8 ...
Presiona el paréntesis para que ya no puedas ir a la derecha, ve a la izquierda
foo es una matriz de 8 punteros a ...
Terminado entre paréntesis, ahora puede ir a la derecha
foo es una matriz de 8 punteros a la función que devuelve ...
Nada más a la derecha, ve a la izquierda
foo es una matriz de 8 punteros a la función que devuelve un puntero a un ...
Continuar a la izquierda
foo es una matriz de 8 punteros a funciones que devuelve un puntero a una constante ...
Continuar a la izquierda
foo es una matriz de 8 punteros a funciones que devuelve un puntero a un puntero constante a un ...
Continuar a la izquierda
foo es una matriz de 8 punteros a funciones que devuelve un puntero a un puntero constante a un carácter ...
Continuar a la izquierda
foo es una matriz de 8 punteros a funciones que devuelve un puntero a una constante puntero a una constante char (¡Completo!)
Más explicación: http://www.unixwiz.net/techtips/reading-cdecl.html
fuente
Mucha gente sugiere leer el especificador de tipo de derecha a izquierda.
En ambas formas, el puntero apunta a datos constantes o de solo lectura.
En la segunda forma, el puntero no se puede cambiar; el puntero siempre apuntará al mismo lugar.
fuente
La diferencia es que sin el extra,
const
el programador podría cambiar, dentro del método, a donde apunta el puntero; por ejemplo:En cambio, eso sería ilegal si la firma fuera
void print_string(const char * const the_string)
Muchos programadores sienten que la
const
palabra clave adicional es demasiado detallada (en la mayoría de los escenarios) y la omiten, aunque sería semánticamente correcta.fuente
En este último te estás garantizando no modificar tanto el puntero como el carácter en el primero solo garantizas que el contenido no cambiará pero puedes mover el puntero
fuente
No hay ninguna razón por la que ninguno de los dos no funcione. Todo lo que
print_string()
hace es imprimir el valor. No intenta modificarlo.Es una buena idea hacer funciones que no modifiquen los argumentos de marca como const. La ventaja es que las variables que no pueden cambiar (o que no desea cambiar) se pueden pasar a estas funciones sin errores.
En cuanto a la sintaxis exacta, desea indicar qué tipo de argumentos son "seguros" para pasar a la función.
fuente
Creo que rara vez es relevante, porque su función no se llama con argumentos como & * the_string o ** the_string. El puntero en sí es un argumento de tipo valor, por lo que incluso si lo modifica, no cambiará la copia que se usó para llamar a su función. La versión que está mostrando asegura que la cadena no cambiará, y creo que eso es suficiente en este caso.
fuente
const char *
significa que no puede usar el puntero para cambiar lo que se apunta. Sin embargo, puede cambiar el puntero para que apunte a otra cosa.Considerar:
El parámetro es un puntero no constante a const char, por lo que se puede cambiar a otro
const char *
valor (como una cadena constante). Sin embargo, si escribimos por error*text = '\0'
, obtendríamos un error de compilación.Podría decirse que si no tiene la intención de cambiar a qué apunta el parámetro, podría hacer que el parámetro
const char * const text
, pero no es común hacerlo. Por lo general, permitimos que las funciones cambien los valores pasados a los parámetros (debido a que pasamos los parámetros por valor, cualquier cambio no afecta al llamador).Por cierto: es una buena práctica evitarlo
char const *
porque a menudo seconst char *
lee mal; significa lo mismo que , pero demasiada gente lo lee como significadochar * const
.fuente
const char *
firma y la míachar const *
, ¡la forma en que redactó su BTW realmente ayudó!Casi todas las otras respuestas son correctas, pero pierden un aspecto de esto: cuando usa el extra
const
en un parámetro en una declaración de función, el compilador esencialmente lo ignorará. Por un momento, ignoremos la complejidad de que su ejemplo sea un puntero y usemos unint
.declara la misma función que
Solo en la definición de la función es más
const
significativo:Esta definición es compatible con cualquiera de las declaraciones anteriores. A la persona que llama no le importa que
x
seaconst
un detalle de implementación que no es relevante en el sitio de la llamada.Si tiene un
const
puntero aconst
datos, se aplican las mismas reglas:Pocos programadores de C ++ se molestan en crear parámetros
const
, incluso cuando podrían serlo, independientemente de si esos parámetros son punteros.fuente
const
a su parámetro de función en la definición pero no en la declaración.La diferencia entre los dos es que char * puede apuntar a cualquier puntero arbitrario. Const char * por el contrario, apunta a las constantes definidas en la sección DATA del ejecutable. Y, como tal, no puede modificar los valores de caracteres de una cadena const char *.
fuente
const char*
puede señalar a cualquier lugar que le plazca.