2010-07-21 17 views
9

¿Por qué los compiladores ANSI C no señalan el uso de un argumento de cadena literal en una llamada de función en la que el parámetro correspondiente no tiene un calificador const? Por ejemplo, el siguiente código podría generar una excepción al intentar escribir en la memoria de solo lectura.Literales de cadena frente a const char * en C

void somefunc(char buffer[10]); 

void somefunc(char buffer[10]) { 
    int i; 

    for (i = 0; i < 10; i++) 
     buffer[i] = 0; 
} 

int main(int argc, char **argv) { 

    somefunc("Literal"); 
    return 0; 
} 

Esta situación se pudo identificar en tiempo de compilación, pero VS2010 y gcc no parecen hacerlo. Llamar a somefunc con un argumento const char * generará una advertencia de compilación.

+0

Buena pregunta: gcc tampoco detecta esto, incluso con '-Wextra'. –

+0

¿Cuál es el punto de declarar una función y luego definirla en la siguiente línea? :) – GManNickG

+0

Hans: He modificado la pregunta para especificar ANSI C. De todos modos, no estaba sugiriendo que se emitiera un error de compilación. Una advertencia de nivel 3 o 4 simplemente resaltaría una situación potencialmente peligrosa. – Robin

Respuesta

11

gcc: Utilice la bandera -Wwrite-strings

PS. El manual de gcc explica por qué esto no es parte de -Wall. De todos modos, como siempre, debe encontrar una combinación de banderas -W que se adapte a sus necesidades particulares y estilo de codificación. Por ejemplo, en un proyecto reciente que he usado algo como esto: -Werror -Wall -Wextra -Wformat=2 -Winit-self -Wswitch-enum -Wstrict-aliasing=2 -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wdisabled-optimization -Wunused-macros -Wno-unused

6

literales de cadena no son const en C; en C++ lo son.

editar: para aclarar cualquier confusión sobre mi comentario, me refiero al tipo, no a la capacidad de realmente cambiarlos.

+1

¿Qué te hace pensar eso? –

+2

@Paul, él está en lo cierto. C99 §6.4.5/5: "Para los literales de cadena de caracteres, los elementos de la matriz tienen el tipo' char' "No está definido para modificar una cadena literal, pero el tipo de elemento es' char', no 'const char'. –

+0

@Matthew: gracias por la aclaración - Interpreté "const" para significar "solo lectura" (que por supuesto los literales de cadena generalmente están en C o C++) pero veo lo que quieres decir con respecto al * tipo * real de la cadena literal ahora –

15

Es un K & R legacy. Arreglarlo rompería un millón de programas.

7

Lo que dijo Hans Passant. const se agregó como parte del estándar ANSI en 1989, por lo que cualquier cosa anterior no tenía const.

+1

@Georg: me refiero a que se agregó la palabra clave const en ANSI C, por lo que ya era demasiado tarde para actualizar los literales de cadenas con constness. – ninjalj

+0

Ah, ahora te entiendo :) –

4

El compilador de GNU (y el compilador Intel C, así, IIRC) emitirá una advertencia, si -Wwrite-string se utiliza:

$ gcc -Wall -Wwrite-strings -o foo /tmp/foo.c 
/tmp/foo.c: In function 'main': 
/tmp/foo.c:12: warning: passing argument 1 of 'somefunc' discards qualifiers from pointer target type 
/tmp/foo.c:3: note: expected 'char *' but argument is of type 'const char *' 

Con respecto a VS2010, no puedo ayudarte.

+1

Genial - Me pregunto por qué '-Wwrite-strings' no está incluido en' -Wall' o incluso '-Wextra' embargo? –

Cuestiones relacionadas