son - ¿Por qué C++ es más restrictivo con respecto a la declaración de prototipos de funciones(firmas)?
que es una funcion dev c++ (5)
Siempre pensé que C es más restrictivo, pero parece que este no es el caso.
Lo tienes al revés. En casi todos los lugares donde C ++ no es un superconjunto de C, es porque C ++ es más restrictivo. El sistema de tipo C ++ es más estricto que el sistema de tipo C, las características heredadas como la que se disparó ("declaración implícita") se eliminan, hay muchas más palabras reservadas, etc.
Es cierto que C ++ tiene muchas más funciones que C, pero no debe confundir la cantidad de funciones que tiene un idioma con la falta de restricciones. Un aspecto importante de la filosofía de diseño de la familia lingüística ML / Haskell es proporcionar muchas características pero también mucha y mucha rigidez.
Noté que C ++ es más restrictivo que C en cuanto a declarar firmas de funciones antes de usarlas, incluso si las definiciones de funciones se declaran después de la función que realmente las llama.
Siempre pensé que C es más restrictivo, pero parece que este no es el caso.
¿Por qué ha cambiado la filosofía al hacer los estándares para el lenguaje de programación C ++?
Por ejemplo, el siguiente código ejecuta compiles fine en el comando gcc
pero genera un error al intentar compilar con g++
#include<stdio.h>
int main()
{
int a=sum(4,6);
printf("%d",a);
return 0;
}
int sum(int a,int b)
{
return a+b;
}
El error es
‘sum’ was not declared in this scope
C originalmente permitía que las funciones se llamaran desde el programa sin haber sido definidas, lo que permitía que fueran "definidas más adelante". Y luego, si no definió la función, el compilador simplemente creó una convención de llamada como "ok, no sé qué devuelve esta función, así que supongamos que devuelve int". Se podrían hacer suposiciones similares para los parámetros ... para los que opcionalmente podría definir los tipos. Las antiguas funciones de "estilo K&R" C parecían
int func (a, b)
int a;
int b;
{
...
}
Para forzar el tipo de los parámetros, tendría que usar el llamado "formato de prototipo", con una declaración hacia adelante como:
int func (int a, int b); // function prototype since the parameter types are explicit
Todo el comportamiento de la declaración de función implícita era una simple tontería peligrosa y conducía a errores fatales. Sin embargo, este comportamiento peligroso se eliminó solo parcialmente en la estandarización de los años 1990. Al compilador todavía se le permitía hacer suposiciones implícitas sobre la función si no se veía ningún prototipo. (Por ejemplo, esta es la razón por la que Malloc solía enloquecer por completo si olvidó incluir stdlib.h).
Esta es la razón por la que su código se compila, está usando una versión anterior de gcc (4.x o más antigua) que por defecto es -std=gnu90
, que usa el estándar C de 1990 años + extensiones no estándar. Versiones más recientes de gcc, 5.0 o posterior, predeterminadas en -std=gnu11
que es el estándar C actual (C11) + extensiones no estándar.
C ++ nunca permitió este comportamiento, y C también lo corrigió con el estándar C99 en el año 1999. Incluso si tiene un compilador gcc antiguo, debería poder compilar con gcc -std=c99 -pedantic-errors
, que significa " En realidad siguen la norma C, versión 1999 años ". Luego se obtienen errores de compilación si no se puede ver una declaración / definición de función adecuada antes de llamar a una función.
Cuando un compilador de C ve una llamada a una función que no conoce, adivina cuál debe ser el valor de retorno y los tipos de parámetros. El tipo de retorno se adivina como int, y los tipos de parámetros se consideran el mismo que el valor pasado después de aplicar las "promociones habituales".
Así que si solo llamas
double result = cube (1);
el compilador adivina que la función "cubo" tiene un argumento de tipo int, y devuelve int.
¿Qué pasa si esa "conjetura" es incorrecta? Difícil. Tiene un comportamiento indefinido, su código puede fallar o peor.
Debido a esta "adivinación", la suma de la llamada (4, 6) está permitida en C, y debido a que la función real tenía todos los tipos correctos (dos argumentos del tipo int, el valor de retorno tiene el tipo) realmente funciona. Pero esto es obviamente algo muy peligroso de hacer.
Debido a que es tan peligroso, C ++ no hace declaraciones implícitas (es decir, el compilador de C ++ no puede adivinar los tipos de argumentos. Por eso no se compila.
Hay algunos idiomas en la actualidad en los que el compilador no necesita una función para ser declarado antes de ser utilizado.
En el estándar C más antiguo (antes de C99), hay una cosa llamada "declaración de función implícita" que se ha eliminado desde C99. Entonces, si compilas en modo C90, un compilador tiene que soportar esa "característica". Mientras que en C ++, la "declaración de función implícita" nunca ha estado allí. Así que los errores de GCC. Tu código tampoco es válido en C moderno (C99 o posterior).
Compile con switches de compilación más estrictos (por ejemplo, -std=c99 -Wall -Wextra -pedantic-errors
) y preste atención a todos los diagnósticos.
Hay muchas razones. Una de ellas es la sobrecarga de funciones:
void func(double);
// void func(int);
int main()
{
func(1);
}
Si descomento la línea con void func(int x);
, se llamará, de lo contrario se promoverá 1 a double
y se void func(double)
.