2011-09-28 28 views
9

Intenté esto en GCC 4.6 y compila y vincula, pero da un mensaje de "error de bus" en tiempo de ejecución en MacOS. VS2010 ni siquiera lo compila.¿Es este código correcto de C++ 0x?

Pero la pregunta es, ¿debería funcionar realmente en el estándar C++ 0x?

#include <cstdio> 
int (*main)()=[]()->int{printf("HEY!\n");return 0;}; 

Sí, lo que intenta hacer es definir "principal" como una función lambda.

+13

Me encanta la forma en que intentas usar las características más avanzadas de C++ 11, pero aún así insistes en usar 'cstdio' y' printf' :-) – paxdiablo

+4

@paxdiablo: printf rocks !!! C++ falló en las transmisiones de E/S :) –

+1

De acuerdo con Stroustroup ... si C le permite disparar en el pie, ¡C++ puede volarse toda la pierna! ¡Esto es lo que yo llamo ... masoquismo! :-)) –

Respuesta

14

Este no es un programa C++ válido, porque el símbolo main no está definido como una función, sino más bien como un puntero a la función. Es por eso que obtiene un error de segmentación: el tiempo de ejecución está intentando ejecutar un puntero.

+0

+1: (Se eliminó mi comentario descuidado a la pregunta original. Esa respuesta explica mejor qué está sucediendo aquí) –

+0

¿Entonces supongo que en realidad es un error en GCC que acepta este código como correcto? – hasvn

+0

@hasvn, no estoy seguro, pero creo que esta es una de esas instancias en las que el estándar no exige ningún diagnóstico. Entonces, gcc podría estar en claro. – avakar

3

No, esto no es correcto.

Main es una función especial y existen requisitos estrictos para ella (incluso más estrictos que una función normal), pero también se crea cierta confusión entre lo que es una función y lo que es un puntero a una función.

El problema lógico es que hay una diferencia entre una función y una variable que contiene un puntero a una función (lo que quiere que sea main). Una función tiene una dirección fija en la memoria, por lo que para llamar a una función esa dirección simplemente se llama. Un puntero a una función señala a una dirección en la memoria, por lo que para llamar a la función necesita primero leer a qué apunta el puntero y luego llamar a esa dirección.

Un puntero a la función tiene un nivel diferente de indirección de una función.

La sintaxis es la misma ... es decir, si x es un puntero a una función que puede escribir x(42), pero aún así el código de máquina generado es diferente si en vez x es una función (en el caso de un puntero un valor debe se debe buscar y la dirección de la llamada se determina en tiempo de ejecución, con una función la dirección se arregla, hasta la reubicación, y se determina en el tiempo del enlace).

0

Para la portabilidad entre compiladores e implementaciones de bibliotecas estándar, printf() debe ser std :: printf() cuando #incluya <cstdio>. Y las otras cosas sobre el principal no válido().

+0

No, no está especificado en el estándar si 'cXXX' incluye la inyección en el espacio de nombres global. Es _util_ usar 'std ::' pero "debe" es probablemente una exageración. – paxdiablo

+0

Bien, esto fue una media broma de todos modos. Editaré la respuesta para señalar que es necesaria para la portabilidad. (Aquellos de nosotros que escribimos el código portátil para ganarnos la vida simplemente comenzamos a pensar de esta manera ...) –

0

Ahora, ni siquiera debería compilar. La expresión lambda produce un tipo (un funtor). No hay conversión implícita de tipo a puntero de función.

Dependiendo del compilador, la función main puede tener un enlace C++ o C (su implementación está definida). La expresión Lambda devuelve el tipo C++ con el operador de llamada de función, por lo tanto, el enlace C++.

+0

En realidad, hay una conversión implícita de un lambda que no captura a un puntero a la función. – avakar

+0

Cita: (5.1.2/6). –

+0

Ambos tienen razón. Sin embargo, se convierte implícitamente en puntero a función miembro, no en función libre. Recordar vagamente eso podría haberme confundido. – mloskot