2009-08-10 13 views
5

Supongo que la mayoría de los compiladores de C++ están escritos en ensamblaje. Lo que los hace diferentes idiomas por completo (podría estar equivocado). Dicho esto, si fuera a crear una función de estilo cout para la antigua C simple, ¿cómo lo haría? cout tiene algunas características muy impresionantes toman este fragmento, por ejemplo:Creando una función cout en C?

// endl not only prints a new line but also flushes the stream 
cout << "Hello World!" << endl; 

Qué estoy bastante seguro de que este se traduce en C:

printf("Hello World!\n"); 
fflush(1);     //stdout = 1 

siguiente orden del día, los operadores <<. En C++ esto sería fácil (sobrecarga del operador), pero no puedo pensar en una sola forma de hacerlo en C.

+2

No está seguro de por dónde empezar en este caso ... La respuesta corta es que el C++ el lenguaje se define para permitir una sintaxis como esta, y el lenguaje C no lo es. - Pero su pregunta podría ser tomada de "¿Cómo escribo un compilador para un lenguaje de extensión C?" todo el camino hasta "¿Cómo puedo duplicar la funcionalidad de iostream en una biblioteca personalizada con macros de estilo C para una sintaxis especial?" –

+0

@Conspicuo compilador: Sé lo que dices. Esa es la razón por la que lo marqué hipotético. No es importante ... solo tengo curiosidad. – Kredns

+4

La mayoría de los compiladores de C++ están escritos en C o C++, y no en ensamblaje. –

Respuesta

5

Correcto, porque C no tiene sobrecarga del operador, no puede cambiar el comportamiento del < < operador, siempre hará un cambio de bit, por lo que no hay forma de escribir 'cout' con la semántica precisa que tiene en C++, en C.

Fuera de interés, g ++ (Compilador GNU C++) está escrito principalmente en C.

4

C es en realidad un lenguaje de implementación popular para compiladores C++ y bibliotecas estándar (así es C++, en realidad, un concepto conocido a veces como autohospedaje o arranque de un lenguaje), y usted puede estudiar las fuentes completas de una biblioteca estándar de C++ compleja y rica (más extensiones) here (lo siento, esto es gcc 3 - no se puede encontrar un árbol fuente gcc 4 que sea fácilmente navegable en línea, aunque por supuesto puede descargar fácilmente esos fuentes y estudiarlos en su máquina local).

Personalmente, yo sugiero comenzar con un buen libro, como this one - las fuentes serán mucho más significativas para usted una vez que tenga una buena comprensión de todos los rincones oscuros de los iostreams de C++ (como un extra, el libro también lo lleva en una visita guiada a través de localidades - ¡aferrarse a su sombrero! -).

8

que puede ayudar a pensar en esto para traducir entre la sintaxis del operador "< <" y la sintaxis de la función "operador < <". Su C++ ejemplo es equivalente a este trozo de código C++:

operator<< (operator<< (cout, "Hello World!"), endl); 

La primera cosa que usted debe notar aquí es que no es en realidad un montón de inteligencia en cout en absoluto. Lo que es inteligente es la función del operador < < - específicamente, la versión del operador < < función que toma un objeto de secuencia (que es lo que cout es, pero muchas otras cosas también lo son) como su primer argumento. O, incluso más precisamente, el rango de operador < < funciones que toman un objeto de secuencia como primer argumento, y toman una cosa particular como el segundo argumento - hay uno para cada tipo de objeto que puede colocar en la secuencia de comandos. También puede ver uno de los trucos de C++ en esa sintaxis; las funciones del operador < < en los objetos de transmisión siempre devuelven el objeto de transmisión que se les asignó, permitiendo así el encadenamiento de esta naturaleza.

Para poner código C++ en enlazadores y ABI de sistema que esperan sintaxis de función C, la mayoría de los compiladores C++ "mangle" los nombres de función, para codificar en ellos el tipo de argumentos que tienen. (Además, por supuesto, el "< <" no es un nombre válido de función tipo C.) Por lo tanto, si mirara el ensamblaje generado para este bit de función, vería que los nombres de las dos funciones eran diferentes entre sí - tendrían sufijos que indican los tipos de argumento.Se podría hacer algo así de forma manual:

operator_lshift__stream__endl(
    operator_lshift__stream__string(cout, "Hello World!"), endl); 

Y ahí lo tienes algo que se podría aplicar en C.