valores sharp que programacion literales descargar definidas constantes caracteristicas c string language-lawyer compiler-warnings string-literals

sharp - ¿Por qué los compiladores de C no advierten sobre tipos incompatibles con cadenas literales?



literales programacion (2)

Hay una opción para esto: -Wwrite-strings . Funciona cambiando el tipo de cadenas literales de char[N] a const char[N] . Este cambio no es compatible con el estándar C y hará que el código válido sea rechazado, y en casos raros, el código no válido se acepta de forma silenciosa. No está habilitado por defecto.

Desafortunadamente, debido a la forma en que se definen los literales de cadena en C, es muy difícil proporcionar buenas advertencias para esto sin cambiar el idioma.

Esta pregunta ya tiene una respuesta aquí:

El siguiente programa provoca un error sistemático de segmentación debido a un comportamiento indefinido (intentando modificar un literal de cadena):

int main() { char *s = "immutable"; s[0] = ''a''; return 0; }

Aún así, parece que no hay absolutamente ninguna manera de decirle a GCC / Clang que emita la más mínima advertencia ( -Wall -Wextra -pedantic -std=c11 no hace nada).

Especialmente para los principiantes, este tipo de situación sería útil para informar. Incluso para los no principiantes, en algunas situaciones un poco menos obvias podría ser útil:

void f(char *s) { s[0] = ''0''; } int main() { char *s = "immutable"; f("literal"); // oops f(s); // oops return 0; }

Además, esto ayudaría a imponer cierta constricción en la programación en C.

¿Por qué estos casos son ignorados deliberadamente? ¿El estándar prohíbe activamente que se emitan diagnósticos en tales casos, o es principalmente por compatibilidad con versiones anteriores (intentar imponerlos ahora generaría demasiadas advertencias)?


Los compiladores de TL; DR C no advierten, porque no "ven" un problema allí. Por definición, los literales de cadena C son matrices de caracteres terminadas en nulo. Sólo se afirma que,

[...] Si el programa intenta modificar dicha matriz, el comportamiento no está definido.

Por lo tanto, en el proceso de compilación, el compilador no sabe que una matriz de caracteres debe comportarse como una cadena literal . Sólo está prohibido el intento de modificación.

Lectura relacionada: para cualquier persona interesada, consulte ¿Por qué los literales de cadena C son de solo lectura?

Dicho esto, no estoy muy seguro de si esta es una buena opción, pero gcc tiene la opción -Wwrite-strings .

Citando el manual en línea ,

-Wwrite-strings

Al compilar C, asigne a las constantes de cadena el tipo const char[length] para que al copiar la dirección de uno en un puntero no const char * aparezca una advertencia. Estas advertencias lo ayudan a encontrar un código de tiempo de compilación que puede intentar escribir en una cadena constante, pero solo si ha sido muy cuidadoso al usar const en declaraciones y prototipos. De lo contrario, es sólo una molestia. Es por esto que no hicimos -Wall solicitar estas advertencias.

Por lo tanto, produce una advertencia utilizando el modo de puerta trasera .

Por definición, los literales de cadena C (es decir, los literales de cadena de caracteres) son matrices de caracteres con terminador nulo. El estándar no les obliga a ser const .

Ref: C11 , capitulo

En la fase de traducción 7, se agrega un byte o código de valor cero a cada secuencia de caracteres multibyte que resulta de un literal de cadena o literales. La secuencia de caracteres multibyte se usa luego para inicializar una matriz de duración y longitud de almacenamiento estático suficiente para contener la secuencia. Para los literales de cadena de caracteres, los elementos de la matriz tienen tipo char y se inicializan con los bytes individuales de la secuencia de caracteres multibyte. [....]

El uso de la opción antes mencionada hace que los literales de cadena consten cualificados, por lo que el uso de un literal de cadena como el RHS de asignación a un puntero de tipo no constante provoca una advertencia.

Esto se hace con referencia a C11 , capítulo §6.7.3

Si se intenta modificar un objeto definido con un tipo de calificación constante mediante el uso de un valor con un tipo no calificado de constante, el comportamiento no está definido. [...]

Por lo tanto, aquí el compilador produce una advertencia para la asignación del tipo cualificado const a un tipo no const .

Relacionado con por qué el uso de -Wall -Wextra -pedantic -std=c11 no produce esta advertencia, es decir, citando la cita una vez más

[...] Estas advertencias lo ayudan a encontrar un código de tiempo de compilación que puede intentar escribir en una cadena constante, pero solo si ha sido muy cuidadoso al usar const en declaraciones y prototipos. De lo contrario, es sólo una molestia. Es por esto que no hicimos -Wall solicitar estas advertencias.