ultima compiler compilador c++ gcc g++

c++ - compiler - gcc ultima version



Inicialización de cero extraño con g++ (6)

Me encontré con un extraño comportamiento del siguiente código, mientras jugaba con la inicialización de ints usando g ++ 4.4.3.

int main() { int x(int()); int y = int(); cout << x << " " << y << endl; }

el resultado es:

1 0

El valor de "y" es 0 como se esperaba, pero el valor de x es extrañamente "1".

En VS2008 produce el siguiente error de enlace (una declaración de función, pero sin definición):

unresolved external symbol "int __cdecl x(int (__cdecl*)(void))"

¿Alguien puede explicar este extraño comportamiento de g ++?


C ++ interpreta el primero como la declaración de una función.


Como han dicho otros, x es una declaración de función. Como no hay un insertador de ostream predefinido definido para los tipos de punteros de función, parece que g ++ usa la conversión bool implícita (utilizada para verificar si el puntero de una función es NULL) para encontrar una manera de generarla.

Visual C ++, por otro lado, se queja de que la función declarada x nunca se define, y por lo tanto no puede completar el enlace. Sospecho que g ++ en este caso es lo suficientemente inteligente como para ver que la función nunca se llama, y ​​por lo tanto no se preocupa por el enlace.

Puede intentar agregar una definición ficticia de la función int x(int(*)()) { return 0xdeadbeef; } int x(int(*)()) { return 0xdeadbeef; } al código y ver qué hace MSVC con él entonces.


Esta

int x(int());

Es en realidad una declaración de función. La entrada es una función de la siguiente firma.

int fn(void)

El puntero de función pasado a std::cout << se convierte en un bool (1) ya que es un puntero que no es NULL.


Para complementar la respuesta de GMan here ( x es una definición de función) en cuanto a por qué el 1 .

La razón para que la salida sea 1 es que en el lugar de la llamada std::cout << x , la función decae en un puntero a la función (el lenguaje no le permite pasar funciones como argumentos a otras funciones, por lo que con matrices se realiza una conversión implícita a puntero a ). Ahora, no hay una sobrecarga de un ostream que tome un puntero de función, y el compilador intenta seleccionar una conversión a cualquiera de las sobrecargas disponibles. En ese punto, encuentra que la mejor secuencia de conversión es bool e imprime 1 (el puntero no es 0).

Puede verificar esto cambiando el comportamiento, puede usar std::cout << std::boolalpha << x , y se imprimirá true lugar de 1 . Además, es interesante notar que VS tiene razón con este, ya que la expresión std::cout << x requiere tomar la dirección de x , luego se usa la función y el programa está mal formado si no hay una definición para esa funcion Puedes verificarlo nuevamente proporcionando una definición:

int f() {} int main() { int x(int()); // 1 x( &f ); // 2 } int x( int(*)() ) { // 3 std::cout << "In x" << std::endl; }

Donde he realizado manualmente la conversión de function a pointer-to-function en la definición de x (1) y la llamada con el argumento f (2) - tenga en cuenta que la declaración en 1 y la definición en 3 son la misma firma , y que el compilador ejecutará el & in x( &f ) si no lo hace.


Simplemente añada más parens:

int main() { int x((int())); int y = int(); cout << x << " " << y << endl; }

Ahora x es un int, no una función.


int x(int()); Se analiza como declaración de función.

Declara una función llamada x , que devuelve un int y acepta un parámetro, que tiene el tipo de una función que devuelve un int y no acepta argumentos.

Esto se conoce como el análisis más molesto.