2010-11-27 6 views
9

ich die Ausgabe des folgenden Programms nicht verstehen:Wann beginnt eine neue __LINE__?

#include <iostream> 

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

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

Die erste Ausgabe ist 7 und 7 anzeigt, dass der Ausbau der FOO eine einzelne logische Linie, aber der zweite Ausgang ist 9 und 10, was anzeigt, zwei verschiedene logische Linien. Warum gibt es einen Unterschied?

Antwort

5

Da

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__ expandiert nach physikalischen Leitungen, keine logischen Linien:

Die Zeilennummer der Stromquellenleitung ist um eins größer als die Anzahl der new-line Zeichen lesen oder in die Übersetzungsphase 1 (2.2) eingeführt, während die Quelldatei zum aktuellen Token verarbeitet wird.

Während die von \ beendet Linien in Übersetzungsphase verkettet 2.

Die andere nur logische Implementierung wäre 3 und 4 für den Aufruf von FOO zu drucken, aber das scheint nicht sehr nützlich.

Sie können auch folgendermaßen aussehen: __LINE__ unterscheidet sich nicht von anderen Makros. Es wird nur automatisch vom Compiler am Anfang jeder Zeile aktualisiert. So wird der Code Art interpretiert die auf diese Weise:

#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'; 
} 

Dies gilt nicht, Code, aber es zeigt, wie die Dinge funktionieren. Wenden Sie die üblichen Makro-Erweiterungsregeln an und Sie erhalten die Ausgabe, die Sie haben.

+0

+1, sehr klare Beschreibung –

+0

Und das ist durch den Standard garantiert? Das wäre großartig! Ich habe einige ziemlich große Makros, die mehrere '__LINE__' Tokens enthalten, und ich würde sie gerne mit umgekehrten Schrägstrichen teilen, aber sie müssen beim Erweitern dieselbe Zeile ergeben. – fredoverflow

+0

@FredOverflow Ja. – ybungalobill

2

Ursache Sie definieren in #define Anweisung, die immer als eine Zeile ausgewertet wird. Der zweite Fall besteht jedoch aus zwei Codezeilen.

3

Da #define Erweiterung enthält Hacker, um sicherzustellen, __LINE__ ist derjenige, wo das Makro "aufgerufen" wird. Sonst würden viele Fehlermeldungen für den Benutzer keinen Sinn ergeben.

+2

Es ist kein Hacker. Es verhält sich wie jedes andere Makro, das Sie vor der Erweiterung von "FOO" definieren und innerhalb von "FOO" verwenden. Die einzige Besonderheit bei '__LINE__' ist, dass es am Anfang jeder Zeile automatisch aktualisiert wird. – ybungalobill

0

Die Substitution von Foo erfordert eine Auswertung der vordefinierten Anweisung _ _LINE _ _. Dies ist, wie ich verstehe, weil es keinen zweiten Vorverarbeitungsdurchlauf gibt, um _ _LINE _ _ auszuwerten.

Daraus ergibt sich die _ _ _ _LINE basiert auf der Linie ausgewertet, auf dem Foo expaned wird, die Linie ist 7.

Die Verwendung von _ _ _ _LINE in der nachfolgenden Zeile im Code wirklich während der ausgewertet wird Vorverarbeitungsphase basierend auf der exakten Zeilennummer, die im Quellcode in der Übersetzungseinheit erscheint.

Verwandte Themen