2010-11-27 6 views
9

Je ne comprends pas la sortie du programme suivant:Quand commence un nouveau __LINE__?

#include <iostream> 

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

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

La première sortie est 7 et 7, ce qui indique que l'expansion de FOO est une seule ligne logique, mais la seconde sortie est 9 et 10, ce qui indique deux lignes logiques distinctes. Pourquoi y a-t-il une différence?

Répondre

5

Parce

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__ se dilate à des lignes physiques, les lignes non logiques:

Le numéro de ligne de la ligne de source de courant est plus grand que le nombre de caractères nouvelle ligne de lecture ou introduit en phase de traduction 1 (2.2) lors du traitement du fichier source sur le jeton en cours.

Alors que les lignes terminées par \ sont concaténés en phase de traduction 2.

L'autre que la mise en œuvre logique serait d'imprimer 3 et 4 pour l'invocation de FOO, mais qui ne semble pas très utile.

Vous pouvez également regarder de la manière suivante: __LINE__ n'est pas différente de toute autre macro. Il est juste mis à jour automatiquement par le compilateur au début de chaque ligne. Donc, le code est interprété comme suit:

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

Ce code n'est pas valide, mais il montre comment les choses fonctionnent. Appliquez les règles habituelles de développement de macros et vous obtiendrez la sortie que vous avez.

+0

+1, description très claire –

+0

Et c'est garanti par la norme? Ce serait génial! J'ai des macros assez volumineuses contenant plusieurs jetons '__LINE__', et je voudrais vraiment les séparer avec des barres obliques inverses, mais elles doivent donner la même ligne lorsqu'elles sont développées. – fredoverflow

+0

@FredOverflow Oui. – ybungalobill

2

cause que vous définissez dans #define instruction qui a toujours évalué comme une ligne. Cependant, le deuxième cas est vraiment deux lignes de code.

3

Parce expansion #define contient hackery pour vous assurer que __LINE__ est celui où la macro est "invoquée". Sinon, beaucoup de messages d'erreur n'auraient aucun sens pour l'utilisateur.

+2

Ce n'est pas un hackery. Il se comporte comme n'importe quelle autre macro que vous "# define" avant l'expansion de "FOO" et utilise dans "FOO". La seule chose spéciale avec '__LINE__' est qu'il est automatiquement mis à jour au début de chaque ligne. – ybungalobill

0

La substitution de Foo nécessite l'évaluation de la directive prédéfinie _ _LINE _ _. Ce que je comprends est parce qu'il n'y a pas de deuxième passage de prétraitement pour évaluer _ _LINE _ _.

D'où le _ _ _ _LINE est évaluée en fonction de la ligne sur laquelle Foo est expaned qui est la ligne 7.

L'utilisation de _ _ _ _LINE dans la ligne suivante dans votre code est vraiment évalué au cours de la phase de prétraitement basée sur le numéro de ligne exact, il apparaît dans le code source dans l'unité de traduction.

Questions connexes