¿Por qué las funciones de valor absoluto en C no aceptan entradas constantes?


23

En C, el prototipo para la función de valor absoluto (que acepta un flotante) es

 float fabsf( float );

¿Por qué este prototipo no acepta un valor constante, como este:

 float fabsf( float const );

fabsf no cambiará el valor de la entrada, ¿verdad?

Si tengo una función que acepta una entrada y llama a fabsf, ¿me veo obligado a evitar especificar la entrada como constante?

¿Cuál es la forma apropiada de manejar la corrección constante en esta situación?


26
constes redundante aquí, ¿qué imaginas que está pasando?
MM

1
@MM Espero que cree un error de tiempo de compilación si intento cambiar el valor de la entrada dentro de la función. ¿Es esto incorrecto?
user24205

16
Dado que el parámetro dentro de la función es una copia local, agregar no consttiene sentido.
Lundin

1
" fabsf no cambiará el valor de la entrada, ¿verdad? " ¿Cómo podría saberlo? El parámetro se pasa por valor.
David Schwartz

El siguiente código es legal C: float const x = -1.0; float y = fabsf(x);me parece que fabsf acepta entradas constantes. No hay forma de decir "puedes pasarme un floatpor valor pero no puedes pasar un const float". (Y como vemos en las respuestas, C no proporciona una manera de exigir que la entrada a una función sea a float const.)
David K

Respuestas:


14

Editar

Como se ha comentado MM, en parámetros en prototipos el constse ignora. La fuente editada de la respuesta original (ver más abajo) muestra esto:

float correct(float const value);

float erroneous(float const value);

float changer(float value);

float correct(float value) {
  return -value;
}

float erroneous(float value) {
  value = -value;
  return value;
}

float changer(float value) {
    value = -value;
    return value;
}

No hay ningún mensaje de error.

De todos modos, dejaré el original en su lugar con la esperanza de que pueda ayudar.


Original

El constparámetro at a hace que este parámetro sea de solo lectura dentro de la función.

Por ejemplo:

float correct(float const value) {
  return -value;
}

float erroneous(float const value) {
  value = -value;
  return value;
}

float changer(float value) {
  value = -value;
  return value;
}

Esta fuente no se compilará sin un mensaje de error.

La función correct()leerá el valor dado, cambiará su signo y devolverá el valor negado.

La función erroneous()parece hacer efectivamente lo mismo, excepto que hay una asignación al parámetro. Pero como el parámetro es constesto no está permitido.

A continuación, la función changer()funcionará como las dos anteriores, pero no da errores.

Veamos el sitio de la llamada:

float f = 3.14159;
float g = correct(f); // or erroneous(f) or changer(f)

La variable fdada como argumento se copiará en el parámetro value. Nunca cambiará incluso si changer()se llamará.

Es posible que desee ver los parámetros como algún tipo de variables locales. En realidad, se manejan principalmente de esta manera en el código de máquina generado.


Entonces, ¿por qué ves a constveces? Lo verá si un puntero se define como parámetro.

Cuando no desea que se cambie el valor señalado , debe agregarlo const; pero hazlo en la posición correcta!

void effective(int const * pointer);

void futile(int * const pointer);

void possible_but_overly_restricted(int const * const pointer);

Sin embargo, la pregunta es acerca de los prototipos, el prototipo float fabsf( float const );no tiene nada que ver con la implementación de la función (que no tiene que repetir const), de hecho, constse ignora por completo en el prototipo
MM

2
¿Puede const entrar en definiciones de funciones sin entrar en el prototipo?
user24205

3
@ user24205 sí, puede
Daniel Jour

33

C utiliza pasar por valor. El valor para el parámetro de una función es una copia del argumento que da.

Está bien copiar flotadores const y no const, y el resultado es un flotador sin const.

Es similar a la asignación:

const float f = 5.5f;
float g = f;   // OK

De hecho, el lenguaje especifica que el valor de una expresión nunca puede ser const, es decir, cuando se lee un valor de una variable, ese valor ni constsiquiera es si la variable lo fuera.


8

Debido a que el lenguaje C usa la semántica de pasar por valor, cualquier argumento que le pase, aunque podría modificarse internamente, no afecta directamente el valor que pasa.

Esto significa que desde la perspectiva de la persona que llama, float fabsf( float );y float fabsf( const float );son lo mismo. Entonces no tiene sentido hacer el parámetro const.

Donde tiene sentido usar constes si el parámetro que pasa es un puntero, por ejemplo:

void print_string(char *str)

Esta función, a pesar de lo que sugiere el nombre, puede desreferenciar el puntero dado y modificar lo que apunta, es decir str[0] = 'x', para dar como resultado un cambio visible por la función de llamada. Si esta función se definiera así:

void print_string(const char *str)

La persona que llama tiene la seguridad de que la función no puede realizar modificaciones a los strpuntos.


"El autor de la llamada se asegura de que la función no puede realizar ninguna modificación ..." no es cierto. La función conoce la dirección de los datos y por lo tanto puede modificarlo, con, por ejemplo: ((char*)str)[0] = 'f'. Por lo tanto, const ... *la lista de argumentos es solo una "declaración de intenciones".
oromoiluig

5

Para agregar una perspectiva de abogado de idiomas:

Para que dos tipos de funciones sean compatibles, ambos deben especificar tipos de retorno compatibles. Además, las listas de tipos de parámetros, si ambas están presentes, deberán coincidir en el número de parámetros y en el uso del terminador de puntos suspensivos; Los parámetros correspondientes deberán tener tipos compatibles . [..] En la determinación de la compatibilidad de tipos y de un tipo compuesto, [..] cada parámetro declarado con tipo calificado se considera que tiene la versión no calificada de su tipo declarado .

N1570 6.7.6.3/15

Eso significa que estos dos son compatibles:

void foo(int const);
void foo(int);

Por lo tanto, puede escribir el prototipo con o sin const(lo que significa que sin tiene más sentido; menos para escribir / leer) y puede agregar constla definición de la función si desea evitar modificar accidentalmente el parámetro (copiado - ¡llamada por valor!) Dentro de las funciones cuerpo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.