Триграфы в комментарии, преобразованные в c ++ 11, игнорируемые в c ++ 17 - PullRequest
0 голосов
/ 15 ноября 2018

Рассмотрим следующий фрагмент кода (обратите внимание на комментарий):

#include <iostream>

int main()
{
    int x = 1; // <-- Why??/
    x += 1;
    std::cout << x << std::endl;
}

Для компиляции этой программы я использую компилятор GNU C ++ g++:

$ g++ --version // g++ (Ubuntu 6.5.0-1ubuntu1~16.04) 6.5.0 20181026

Теперь, при компиляции для C ++ 11 и C ++ 17 , я получаю разные результаты (и предупреждения).

Для C ++ 11, g++ -std=c++11 trigraph.cpp -Wall:

trigraph.cpp:5:26: warning: trigraph ??/ converted to \ [-Wtrigraphs]
         int x = 1; // <-- Why??/

trigraph.cpp:5:16: warning: multi-line comment [-Wcomment]
         int x = 1; // <-- Why??/
                    ^
$ ./a.out
1

Для C ++ 17, g++ -std=c++17 trigraph.cpp -Wall:

trigraph.cpp:5:26: warning: trigraph ??/ ignored, use -trigraphs to enable [-Wtrigraphs]
     int x = 1; // <-- Why??/

$ ./a.out
2

Прочитав немного о триграфах, я понимаю, что они были удалены в C ++ 17, поэтому игнорируются компилятором, как показано в примере выше. Однако, в случае C ++ 11, даже когда он находится в комментарии, он был преобразован!

Теперь я вижу, как это повлияет на код, если, например, триграф был в символьной строке. Но в этом примере не следует ли его игнорировать, поскольку он находится в комментарии?

После удаления косой черты ("/") из комментария все предупреждения исчезли. У меня вопрос, что именно здесь произошло? Почему вывод отличается?

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Триграф ??/ преобразуется компилятором в \ до фактической компиляции (то есть до удаления комментариев).

Итак, эти строки

int x = 1; // <-- Why??/
x += 1;

конвертируется в

int x = 1; // <-- Why\
x += 1;

Обратная косая черта в конце строки добавляет к ней следующую строку. Так становится

int x = 1; // <-- Why    x += 1;

Что перемещает оператор x+=1; в комментарий и, следовательно, не компилируется.

Когда вы удаляете конечный /, он больше не является триграфом (теперь это только ??), и ничего особенного не происходит.

0 голосов
/ 15 ноября 2018

Триграфы - это очень старый способ вставлять в код определенные символы, которые, возможно, были доступны не для всех клавишных комбинаций.Полный список см. В cppreference .

. В вашем примере вы случайно создали один из триграфов ??/, который переводится в \.Трейлинг \ имеет особое значение - он указывает компилятору игнорировать разрыв строки и рассматривать следующую строку как часть текущей строки.

Ваш код будет переведен так:

int x = 1; // <-- Why??/
x += 1; 

int x = 1; // <-- Why\
x += 1;

int x = 1; // <-- Why x += 1;

Вот что на самом деле означают предупреждения.Trigraph был интерпретирован и изменен на \, и он создал многострочный комментарий, даже если вы использовали //.

Теперь триграфы стали устаревшими в C ++ 11 и были удалено из стандарта в C ++ 17.Это означает, что при компиляции в C ++ 11 ваш триграф был переведен, но в C ++ 17 он был проигнорирован (и компилятор отправил вам сообщение о том, что вы все еще можете их включить).

0 голосов
/ 15 ноября 2018

Если ??/ преобразуется в \, то ??// будет преобразовано в \/.

Или // также запускает комментарий, поэтому на первом месте стоит правило применения триграфов, итолько после этого компилятор проверяет, является ли это комментарием или нет.

...