He estado mirando un código fuente, y me encontré con este código
static char const *const delimit_method_string[] = { "none", "prepend", "separate", NULL }; Pensé que sabía el significado de la palabra clave const en el lenguaje C , pero después de ver esta sintaxis, estoy confundido porque no puedo decodificar el significado de la sintaxis, así que quería saber el significado de usar const así. Busqué en Internet y vi algunas preguntas como esta en stackoverflow que son,
Pero aún no entiendo cuál es el significado de la sintaxis en ese fragmento de código, puede ser porque no soy lo suficientemente bueno con los fundamentos de C , pero realmente me gusta mejorarlo.
Así que escribí un código para saber cómo funciona esa sintaxis, esto es lo que probé:
#include <stdio.h> int main() { char a = 'A'; char b = 'B'; char const * const ptr = &a; ptr = &b; printf("a is %c\n", *ptr); printf("a is %c", a); return 0; }Obtuve esta salida, que algo esperaba.
$ gcc test.c test.c: In function 'main': test.c:9:13: error: assignment of read-only variable 'ptr' 9 | ptr = &b; | ^Cambié el código y volví a probar,
#include <stdio.h> int main() { char a = 'A'; char b = 'B'; char const const *ptr = &a; ptr = &b; printf("a is %c\n", *ptr); printf("a is %c", a); return 0; }esta vez el resultado no es lo que esperaba,
$ ./a.exe a is B a is A Realmente aprecio si alguien puede explicar cuál es la forma correcta de usar const en C y también cómo funciona la sintaxis en el primer fragmento de código.
Esta declaración
static char const *const delimit_method_string[] = { "none", "prepend", "separate", NULL }; declara una matriz con el nombre delimit_method_string de punteros a literales de cadena.
En C, opuesto a C++, los literales de cadena tienen tipos de matrices de caracteres no constantes. Sin embargo, no puede cambiar un literal de cadena. Cualquier intento de cambiar un literal de cadena da como resultado un comportamiento indefinido. Por lo tanto, es mejor declarar punteros a literales de cadena de la siguiente manera, por ejemplo
const char *s = "Hello";Entonces podría declarar la matriz anterior como
static char const * delimit_method_string[] = { "none", "prepend", "separate", NULL };Pero el programador que declaró este arreglo también quería declarar at como un arreglo constante. Es decir, quería que sus elementos no se puedan cambiar.
Para la declaración anterior puede escribir por ejemplo
delimit_method_string[0] = "all";Para evitar tal cambio, los elementos de la matriz deben ser constantes. Para ello es necesario escribir
static char const * const delimit_method_string[] = { "none", "prepend", "separate", NULL }; Ahora los elementos de la matriz que tienen el tipo de puntero const char * son constantes debido al segundo calificador const.
Tom deja más claro considerar las siguientes declaraciones.
char *p; Esta declaración declara un puntero no constante a un objeto no constante del tipo char .
const char *p; Esta declaración declara un puntero no constante a un objeto constante del tipo char .
const char * const p; Esta declaración declara un puntero constante a un objeto constante del tipo char .
La última declaración se puede reescribir como
const char ( * const p );En cuanto a esta su declaración
char const const *ptr = &a; entonces uno de los dos calificadores const es redundante porque ambos se refieren al especificador de tipo char .
char const const *ptr = &a; Esta doble const no tiene ningún significado especial ya que ambas están en el mismo lado del * . El compilador ignora los calificadores const adicionales. Puede escribir char const const const const const*ptr = &a; Es lo mismo que char const *ptr = &a; lo que significa:
pointer to constant characterSi lo cambiamos a
char const * const ptr = &a;Significará:
constant pointer to constant charTu fragmento dejará de compilarse: https://godbolt.org/z/sM9qnv8fq
ejemplos:
const int *ptr; - puntero a entero constanteint * const ptr; - puntero constante a enteroconst int * const ptr; - puntero constante a entero constante Su primer ejemplo static char const *const delimit_method_string[] declara:
static array of constant pointers to constant characterPor cierto, personalmente prefiero tener la primera const antes del tipo, es decir:
static const volatile char *const delimit_method_string[]
const char *p