2012-03-01 10 views
8
#include <iostream> 
#define true false 
#define false true 
int main() { 
    std::cout << false << true; 
} 

¿Por qué da salida "01"?¿Cuál es el resultado esperado al redefinir de verdadero a falso y viceversa?

+23

¿En serio? Usted escribió ese código? Para definir 'true' a' false' y viceversa? Encuentra el zapato más cercano y golpéate la cabeza varias veces hasta que descubras cuál es el problema. –

+1

No escribí este código (= Solo quiero entender – hired777

+2

Probablemente se pueda explicar con un hecho poco conocido, generalmente oscuro (pero muy relevante en algunos casos) con respecto a la expansión macro, pero cuando comienzas a citar el estándar, también podría cortocircuitarse e indicar lo que ya dijo Jerry Coffin. En lo que respecta al ISO, el compilador podría iniciar una revolución de robots y hacer que los robots le ganaran al autor con el zapato más cercano para hacer feliz a @CodyGray. – delnan

Respuesta

13

Como señala Jerry Coffin, no puede definir una macro con un nombre que sea una palabra clave.

Sin embargo, podríamos considerar otro ejemplo similar, con un comportamiento bien definido y el mismo resultado. Consideremos:

int TRUE = 1; 
int FALSE = 0; 

#define TRUE FALSE 
#define FALSE TRUE 

std::cout << FALSE << TRUE; 

Cuando se utiliza FALSE, que se identifica como la macro FALSE y se sustituye por la lista de reemplazo de esa macro, que es la señal única, TRUE. Ese reemplazo es entonces vuelto a escanear para obtener más macros para reemplazar.

El TRUE en el reemplazo se identifica entonces como una macro y se reemplaza por su lista de reemplazo, que es el único token FALSE. Ese reemplazo nuevamente se vuelve a explorar.

Si continuamos con el nuevo escaneo y el reemplazo, terminaríamos en un ciclo infinito, por lo que las especificaciones de preprocesamiento C (y C++) indican que el reemplazo macro nunca se repite dentro de una lista de reemplazo.

Desde sustitución de FALSE en esta lista sustitución final resultaría en la recursividad, la sustitución macro se detiene y nos queda FALSE, que es el nombre de un int con un valor de 0.

+0

¡Buena explicación! Pero solo una pregunta, ¿le estás dando ideas para escribir más código como el anterior? – noMAD

+0

Él no lo escribió. –

+5

@noMAD: No, normalmente uno no debería escribir código como este, pero eso no significa que no deberíamos explicar por qué este código funciona de la manera en que lo hace. Es importante entender cómo funciona su lenguaje de programación, incluso en los rincones "tontos" del lenguaje que "nadie usa". Para el registro, he escrito el código exactamente así, en una prueba unitaria para una implementación del preprocesador C en el que estuve trabajando durante un tiempo (claro, tengo pasatiempos extraños). –

11

Cualquier intento de redefinir una palabra reservada proporciona un comportamiento indefinido.

Editar:

§2.11/1: "Los identificadores se muestran en la Tabla 3 están reservados para uso como palabras clave" No intentaré reproducir todo el cuadro 3, pero incluye tanto falso como verdadero. Sin embargo, puede estar abierto a dudas si esta es una prohibición absoluta, ya que la misma oración agrega: "(es decir, se tratan incondicionalmente como palabras clave en la fase 7)", lo que sugiere que es posible redefinir las palabras clave. De esta forma, sin embargo, también ha incluido <iostream>, que trae otra regla en juego (§17.4.3.1.1): "Una traducción la unidad que incluye un encabezado no debe contener macros que definan nombres declarados o definidos en ese encabezado. Tampoco dicha unidad de traducción definirá macros para nombres léxicamente idénticos a palabras clave ".

La redacción aquí sugiere fuertemente que existe la intención de que si una unidad de traducción no incluía ningún encabezado, sería libre de redefinir una palabra clave como lo ha hecho, pero dada la presencia del #include <iostream>, hay no hay duda de que tiene un comportamiento indefinido.

Una vez que tiene un comportamiento indefinido, ya no hay nada más que decir sobre "por qué" sucede cualquier cosa, en ese punto, el estándar es muy claro de que cualquier comportamiento es permisible.

+0

Plz, enlace a ISO – hired777

+1

¿Por qué no solo ve y ve a través de la ISO en lugar de pedirle un "enlace"? De todos modos, los enlaces de "enlace a ISO" al documento, por lo que no le daría nada nuevo. – Griwes

+0

Lo veo a través de él, pero no puedo encontrar la explicación – hired777

Cuestiones relacionadas