2012-01-31 10 views
13

Imagínese que tengo esta función C (y el prototipo correspondiente en un archivo de cabecera)¿Es un comportamiento indefinido desechar la consistencia de un parámetro de función?

void clearstring(const char *data) { 
    char *dst = (char *)data; 
    *dst = 0; 
} 

¿Hay un comportamiento no definido en el código anterior, fundición de la const distancia, o es sólo una práctica terriblemente mala programación ?

Supongamos que no hay objetos const cualificado utilizan

char name[] = "pmg"; 
clearstring(name); 
+2

Si el yeso no es UB, creo que debería ser :) – pmg

+0

¡sin duda tiene su pie de lleno en la mira de escopeta! –

+1

@pmg: si el elenco en sí fuera UB, entonces no tiene sentido que el lenguaje lo permita, es bastante fácil para un compilador detectar que 'const' ha sido agregado en un molde, de la misma manera que detecta que' char * dst = data; 'es ilegal. Obviamente, hay algunas cosas inútiles que el estándar permite por razones históricas, pero afirmo que este no es uno de ellos :-) –

Respuesta

20

El intento de escribir en *dst es UB si la persona que llama se pasa un puntero a un objeto constante, o un puntero a una cadena literal.

Pero si la persona que llama le pasa un puntero a datos que de hecho son mutables, entonces se define el comportamiento. Crear un const char* que apunte a un char modificable no hace que char sea inmutable.

Así:

char c; 
clearstring(&c); // OK, sets c to 0 
char *p = malloc(100); 
if (p) { 
    clearstring(p); // OK, p now points to an empty string 
    free(p); 
} 
const char d = 0; 
clearstring(&d); // UB 
clearstring("foo"); // UB 

Es decir, es muy poco aconsejable su función, porque es muy fácil para una persona que llama a causa de la UB. Pero de hecho es posible usarlo con un comportamiento definido.

+4

+1: (im) la mutabilidad es una propiedad inherente del objeto en sí, independientemente de la calificación del puntero utilizado para acceder ... – Christoph

+0

¿Es este UB debido a 'C99 6.6 §9' o debido a' C99 6.7.3 §5'? – Lundin

+1

@Lundin: este último (y 6.4.5/6 en lugar de 6.7.3/5 en el caso del literal de cadena, ya que los literales de cadena no son objetos 'const' en C). Las constantes de dirección no tienen nada que ver con esto. –

0

Considere una función como strstr que, si se le da un puntero a una parte de un objeto que contiene una cadena, devuelve un puntero a una parte posiblemente diferente del mismo objeto. Si el método pasa un puntero a un área de solo lectura de la memoria, devolverá un puntero a un área de solo lectura de la memoria; Del mismo modo, si se le da un puntero a un área de escritura, devolverá un puntero a un área de escritura.

No hay forma en C para tener una función devuelve un const char * cuando se les da un const char *, y devolver una ordinaria char * cuando se les da un ordinario char *. Para ser compatible con la forma en que strstr funcionó antes de que se añadiera al lenguaje la idea de const char *, debe convertir un puntero calificado en const en un puntero no calificado. Si bien es cierto que como una función de biblioteca strstr podría tener derecho a hacer tal conversión incluso si el código de usuario no pudiera hacerlo, el mismo patrón aparece con suficiente frecuencia en el código de usuario que sería práctico prohibirlo.

Cuestiones relacionadas