Когда начинается новый __LINE__? - PullRequest
9 голосов
/ 27 ноября 2010

Я не понимаю вывод следующей программы:

#include <iostream>

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

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

Первый вывод - 7 и 7, что указывает на то, что расширение FOO представляет собой одну логическую строку, а второй вывод - 9 и 10, что указывает на две различные логические строки. Почему есть разница?

Ответы [ 4 ]

5 голосов
/ 27 ноября 2010

Поскольку

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__ расширяется до физических строк, а не логических строк:

номер строки текущей строки источника равен единицебольше, чем число символов новой строки, прочитанных или введенных на этапе 1 (2.2) перевода при обработке исходного файла в текущий токен.

В то время как строки, заканчивающиеся на \, объединяются в переводеФаза 2.

Другой единственной логической реализацией было бы напечатать 3 и 4 для вызова FOO, но это кажется не очень полезным.

Вы также можете посмотреть на это следующим образом:__LINE__ ничем не отличается от любого другого макроса.Он просто автоматически обновляется компилятором в начале каждой строки.Таким образом, код как бы интерпретируется следующим образом:

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

Это неверный код, но он демонстрирует, как все работает.Примените обычные правила расширения макросов, и вы получите полученный результат.

3 голосов
/ 27 ноября 2010

Поскольку расширение #define содержит хакеры, чтобы убедиться, что __LINE__ является тем, где макрос вызывается.В противном случае многие сообщения об ошибках не будут иметь смысла для пользователя.

2 голосов
/ 27 ноября 2010

вызывает тот, который вы определяете в операторе #define, который всегда оценивается как одна строка. Однако второй случай - это две строки кода.

0 голосов
/ 27 ноября 2010

Подстановка Foo требует оценки предопределенной директивы _ _LINE _ _. Это, как я понимаю, потому, что нет второго этапа предварительной обработки для оценки _ _LINE _ _.

Следовательно, _ _LINE _ _ оценивается на основе строки, на которой расширяется Foo, которая является строкой 7.

Использование _ _LINE _ _ в следующей строке в вашем коде действительно оценивается на этапе предварительной обработки на основе точного номера строки, который появляется в исходном коде в блоке перевода.

...