Se deben utilizar calificadores de tipo inútiles sobre los tipos de retorno, para mayor claridad?

StackOverflow https://stackoverflow.com/questions/1579435

Pregunta

Nuestra herramienta de análisis estático se queja de un "calificador de tipo inútil en el tipo de retorno" cuando tenemos prototipos en la cabecera de archivos tales como:

const int foo();

define de esta manera debido a que la función se vuelve una constante que nunca cambio, el pensamiento de que la API parecía más clara con const en su lugar.

Siento que esto es similar a la inicialización de las variables globales de manera explícita a cero para mayor claridad, a pesar de que el estándar C ya establece que todas las variables globales se inicializan a cero si no inicializado de forma explícita. Al final del día, lo que realmente no importa. (Sin embargo, la herramienta de análisis estático no se queja de eso.)

Mi pregunta es, ¿hay alguna razón por la que esto podría causar un problema? Debemos ignorar los errores generados por la herramienta, o debemos aplacar a la herramienta aún a costa de un API menos clara y consistente? (Se devuelve otras constantes const char* que la herramienta no tiene un problema con.)

¿Fue útil?

Solución

Por lo general es mejor para su código para describir la mayor precisión posible lo que está pasando. Usted está recibiendo esta advertencia porque el const en const int foo(); es básicamente sin sentido. La API sólo parece más claro si usted no sabe lo que el const medio de palabras clave. No sobrecargue el sentido de esa manera; static es bastante malo como es, y no hay razón para añadir el potencial para una mayor confusión.

const char * significa algo diferente que const int hace, por lo que su herramienta no se queja de ello. El primero es un puntero a una cadena constante, es decir, cualquier código que llama a la función que devuelve ese tipo no debe tratar de modificar el contenido de la cadena (que podría ser en la ROM, por ejemplo). En este último caso, el sistema no tiene manera de hacer cumplir que no realiza cambios en el int regresado, por lo que la clasificación no tiene sentido. Un paralelo más cercano a los tipos de retorno sería:

const int foo();
char * const foo2();

que en ambos casos la causa de su análisis estático para dar la advertencia - añadiendo un calificador const a un valor de retorno es una operación sin sentido. Que sólo tiene sentido cuando se tiene un parámetro de referencia (o tipo de retorno), al igual que su ejemplo const char *.

De hecho, acabo de hacer un pequeño programa de prueba, y GCC advierte incluso explícitamente sobre este problema:

test.c:6: warning: type qualifiers ignored on function return type

Así que no es sólo su programa de análisis estático que se queja.

Otros consejos

Se puede usar una técnica diferente para ilustrar su intento sin hacer las herramientas infeliz.

#define CONST_RETURN

CONST_RETURN int foo();

Usted no tiene un problema con const char * porque eso es declarar un puntero a caracteres constantes, no un puntero constante.

Haciendo caso omiso de la const por ahora, foo() devuelve un valor. Usted puede hacer

int x = foo();

y asignar el valor devuelto por foo() a la x variables, casi de la misma manera que puede hacer

int x = 42;

para asignar el valor de la variable x 42.
Pero no se puede cambiar el 42 ... o el valor devuelto por foo(). Diciendo que el valor devuelto por foo() no se puede cambiar, mediante la aplicación de la palabra clave const al tipo de foo() logra nada.

Valores no puede ser const ( o restrict o volatile ). Sólo los objetos pueden tener calificadores de tipo.


Contraste con

const char *foo();

En este caso, foo() devuelve un puntero a un objeto. El objeto apuntado por el valor devuelto puede ser const calificado.

El int es devuelto por copiar . Puede ser una copia de una constante, pero cuando se asigna a otra cosa, algo que, en virtud del hecho de que era asignable, no puede, por definición, una constante.

El const palabra clave tiene la semántica específicos dentro de la lengua, mientras que aquí se está haciendo un mal uso esencialmente como un comentario. En lugar de añadir claridad, se sugiere más bien una falta de comprensión de la semántica del lenguaje.

const int foo() es muy diferente de const char* foo(). const char* foo() devuelve una matriz (por lo general una cadena) cuyo contenido no está permitido cambiar. Piense en la diferencia entre:

 const char* a = "Hello World";

y

const int b = 1;

a sigue siendo una variable y se puede asignar a otras cadenas que no pueden cambiar mientras que b no es una variable. Así

const char* foo();
const char* a = "Hello World\n";
a = foo();

se permite pero

const int bar();
const int b = 0;
b = bar();

no está permitido, incluso con la declaración de const bar().

Sí. Yo aconsejaría escribir código "explícitamente", ya que hace más claro para cualquiera (incluido usted) cuando se lee el código de lo que quería decir. Está escribiendo código para otros programadores para leer , no para complacer los caprichos de las herramientas de compilación y análisis de estática!

(Sin embargo, usted tiene que tener cuidado de que cualquier "código innecesario" no causa código diferente que se genere!)

Algunos ejemplos de codificación explícita mejorar la legibilidad / mantenimiento:

  • I coloque los soportes alrededor de porciones de expresiones aritméticas para especificar explícitamente lo que quiero que suceda. Esto hace que sea claro para cualquier lector de lo que quería decir, y me ahorra tener que preocuparse por (o hacer ay errores con) las reglas de prioridad:

    int a = b + c * d / e + f;      // Hard to read- need to know precedence
    int a = b + ((c * d) / e) + f;  // Easy to read- clear explicit calculations
    

  • En C ++, si reemplaza una función virtual, a continuación, en la clase derivada puede declarar que sin mencionar "virtual" en absoluto. Cualquiera que lea el código no se puede decir que es una función virtual, que puede ser engañoso desastrosa! Sin embargo se puede utilizar con seguridad la palabra clave virtual:

    virtual int MyFunc()
    y esto hace que sea claro para cualquier persona que lee el encabezado de la clase que este método es virtual. (Esta "C ++ error de sintaxis" se fija en C #, al exigir el uso de la palabra clave "anular" en este caso - una prueba más de que si alguien necesitaba que la carencia de la "virtual innecesario" es realmente una mala idea)

Estos son dos ejemplos claros donde la adición de código de "innecesaria" hará que el código sea más legible y menos propenso a errores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top