while usando suma que programacion programa numero funciones funcion for factoriales con calcule c++ compilation linker language-lawyer undefined-function

usando - programacion c++ factorial numero



¿Por qué el enlazador de C++ permite funciones indefinidas? (3)

Lo que sucede aquí es que el puntero a la función se convierte implícitamente a bool . Esto es especificado por [conv.bool] :

Un valor cero, un valor de puntero nulo o un valor de puntero de miembro nulo se convierte en false ; cualquier otro valor se convierte en true

donde "valor de puntero nulo" incluye punteros de función nula. Dado que el puntero de función obtenido de la caída de un nombre de función no puede ser nulo, esto da true . Puede ver esto incluyendo << std::boolalpha en el comando de salida.

Lo siguiente causa un error de enlace en g ++: (int)x;

Con respecto a si este comportamiento está permitido o no, C ++ 14 [basic.odr.ref]/3 dice:

Una función cuyo nombre aparece como una expresión potencialmente evaluada es odr-used si es el resultado de búsqueda único o el miembro seleccionado de un conjunto de funciones sobrecargadas [...]

lo que cubre este caso, ya que x en la expresión de salida se busca en la declaración de x anterior y ese es el único resultado. Entonces en /4 tenemos:

Cada programa contendrá exactamente una definición de cada función o variable no en línea que se utiliza en ese programa; no requiere diagnóstico

por lo tanto, el programa está mal formado pero no se requiere ningún diagnóstico, lo que significa que el comportamiento del programa es completamente indefinido.

Incidentalmente, esta cláusula implica que no se requiere ningún error de enlace para x(); cualquiera, sin embargo, desde un ángulo de calidad de implementación; eso seria tonto El curso que g++ ha elegido aquí me parece razonable.

Este código C ++, tal vez sorprendentemente, imprime 1 .

#include <iostream> std::string x(); int main() { std::cout << "x: " << x << std::endl; return 0; }

x es un prototipo de función, que parece ser visto como un puntero de función, y C ++ Standard sección 4.12 conversiones booleanas dice:

4.12 Conversiones booleanas [conv.bool] 1 Un prvalor de aritmética, enumeración sin ámbito, puntero o puntero a tipo de miembro se puede convertir a un prvalor de tipo bool. Un valor cero, un valor de puntero nulo o un valor de puntero de miembro nulo se convierte en falso; Cualquier otro valor se convierte en verdadero. Para la inicialización directa (8.5), un prvalue de tipo std :: nullptr_t se puede convertir en un prvalue de tipo bool; el valor resultante es falso.

Sin embargo, x nunca está vinculado a una función. Como es de esperar, el enlazador en C no permite esto. Sin embargo, en C ++ esto no es un problema en absoluto. ¿Alguien puede explicar este comportamiento?


[basic.def.odr] / 2:

Una función cuyo nombre aparece como una expresión potencialmente evaluada es odr-used si es el resultado de búsqueda único o el miembro seleccionado de un conjunto de funciones sobrecargadas (3.4, 13.3, 13.4), a menos que sea una función virtual pura y su nombre no está explícitamente calificado.

Por lo tanto, estrictamente hablando, el código odr-usa la función y por lo tanto requiere una definición.
Pero los compiladores modernos se darán cuenta de que la dirección exacta de las funciones no es realmente relevante para el comportamiento del programa y, por lo tanto, ignorarán el uso y no requerirán una definición.

También tenga en cuenta lo que [basic.def.odr] / 3 especifica:

Cada programa contendrá exactamente una definición de cada función o variable no en línea que se utiliza en ese programa; no requiere diagnóstico

Una implementación no está obligada a detener la compilación y emitir un mensaje de error (= diagnóstico). Puede hacer lo que considere mejor. En otras palabras, cualquier acción está permitida y tenemos UB.


X no necesita estar "vinculado" a una función, porque usted indicó en su código que dicha función existe. Así que el compilador puede asumir con seguridad que la dirección de esta función no debe ser NULL. Para que eso sea posible, tendrías que declarar que la función es un símbolo débil, y no lo hiciste. Linker no protestó, porque nunca llama a su función (nunca usa su dirección real), por lo que no ve ningún problema.