2010-11-27 10 views
9

No entiendo la salida del siguiente programa:¿Cuándo comienza un nuevo __LINE__?

#include <iostream> 

#define FOO std::cout << __LINE__ << ' ' \ 
         << __LINE__ << '\n'; 
int main() 
{ 
    FOO 

    std::cout << __LINE__ << ' ' \ 
       << __LINE__ << '\n'; 
} 

La primera salida es 7 y 7, lo que indica que la expansión de FOO es una sola línea lógica, pero la segunda salida es 9 y 10, indicando dos líneas lógicas distintas ¿Por qué hay una diferencia?

Respuesta

5

Debido

1: #include <iostream> 
2: 
3: #define FOO std::cout << __LINE__ << ' ' \ 
4:      << __LINE__ << '\n'; 
5: int main() 
6: { 
7:  FOO // the first two __LINE__s come from here, that's one line of code 
8: 
9:  std::cout << __LINE__ << ' ' \ // 3rd __LINE__ comes from here 
10:    << __LINE__ << '\n'; // 4th __LINE__ comes from here 
11: } 

__LINE__ expande a líneas físicas, líneas no lógicos:

El número línea de la línea de fuente de corriente es uno mayor que el número de la nueva línea de caracteres leídos o introducido en la fase de traducción 1 (2.2) mientras se procesa el archivo fuente al token actual.

Mientras que las líneas que terminaron por \ se concatenan en fase de traducción 2.

La otra aplicación lógico sería imprimir 3 y 4 para la invocación de FOO, pero eso no parece muy útil.

También puede ver esto de la siguiente manera: __LINE__ no es diferente de cualquier otra macro. Se acaba de actualizar automáticamente por el compilador al comienzo de cada línea. Así que el código es una especie de interpretarse de esta manera:

#include <iostream> 

#define __LINE__ 3 
#define FOO std::cout << __LINE__ << ' ' \ 
         << __LINE__ << '\n'; 
int main() 
{ 
#define __LINE__ 7 
    FOO 

#define __LINE__ 9 
    std::cout << __LINE__ << ' ' \ // Yeah, you're right 
#define __LINE__ 10 
      << __LINE__ << '\n'; 
} 

Esto no es un código válido, pero demuestra cómo funcionan las cosas. Aplique las reglas de expansión macro habituales y obtendrá la salida que tiene.

+0

+1, descripción muy clara –

+0

¿Y esto está garantizado por la norma? ¡Eso seria genial! Tengo algunas macros bastante grandes que contienen múltiples tokens '__LINE__', y realmente me gustaría dividirlas con barras diagonales inversas, aunque deben ceder la misma línea cuando se expanden. – fredoverflow

+0

@FredOverflow Sí. – ybungalobill

2

causa que defina en la declaración #define que siempre se evalúa como una línea. Sin embargo, el segundo caso es realmente dos líneas de código.

3

Porque la expansión #define contiene hackeo para asegurarse de que __LINE__ es el que "invoca" la macro. De lo contrario, muchos mensajes de error no tendrían sentido para el usuario.

+2

No es hackeo. Se comporta como cualquier otra macro que usted '# define' antes de la expansión de' FOO' y use dentro de 'FOO'. Lo único especial con '__LINE__' es que se actualiza automáticamente al comienzo de cada línea. – ybungalobill

0

La sustitución de Foo requiere la evaluación de la directiva predefinida _ _LINE _ _. Como entiendo, esto se debe a que no hay un segundo pase de preprocesamiento para evaluar _ _LINE _ _.

ahí la _LINE _ _ _ se evalúa en base a la línea en la que está siendo expaned Foo, que es la línea 7.

El uso de _LINE _ _ _ en la línea siguiente en el código que realmente está evaluado durante el fase de preprocesamiento basada en el número de línea exacto que aparece en el código fuente en la unidad de traducción.

Cuestiones relacionadas