Подтвердить что ты не робот

Почему "\?" escape-последовательность в C/С++?

В C/С++ есть четыре специальных символа без алфавита: одиночная кавычка \', двойная кавычка \", обратная косая черта \\ и вопросительный знак \?. Это, по-видимому, потому, что они имеют особые значения. ' для одиночных char, " для строковых литералов, \ для escape-последовательностей, но почему ? один из них?

Я прочитал таблицу escape-последовательностей в учебнике сегодня, и я понял, что у меня никогда побег ? раньше и никогда не возникал проблемы с ним, просто чтобы убедиться, что я его протестировал под gcc:

#include <stdio.h>
int main(void)
{
    printf("question mark ? and escaped \?\n");
    return 0;
}

и версия С++:

#include <iostream>
int main(void)
{
    std::cout << "question mark ? and escaped \?" << std::endl;
    return 0;
}

Оба выхода программ: question mark ? and escaped ?

У меня есть два вопроса:

  • Почему \? один из символов escape-последовательности?
  • Почему не выполняется экранирование ? работает нормально, там даже не появляется предупреждение.

Прежде чем я собираюсь задать этот вопрос, я нашел ответ сам, так как я не нашел дубликата в SO, я решил опубликовать его в стиле Q & A.

Более интересным фактом является то, что экранированный \? может использоваться так же, как и ? на некоторых других языках, я тестировался в Lua/Ruby, это правда, даже если я не нашел это документированным.

4b9b3361

Ответ 1

Почему \? один из символов escape-последовательности?

Поскольку он является особенным, ответ приводит к Trigraph, препроцессор C/С++ заменяет следующую трехсимвольную последовательность на соответствующий одиночный знак. (C11 §5.2.1.1 и С++ 11 §2.3)

Trigraph:       ??(  ??)  ??<  ??>  ??=  ??/  ??'  ??!  ??-
Replacement:      [    ]    {    }    #    \    ^    |    ~

Trigraph теперь почти бесполезен, в основном используется для запутанных целей, некоторые примеры можно увидеть в IOCCC.

gcc по умолчанию не поддерживает триграф и будет предупреждать вас, если в коде есть триграф, если только опция -trigraphs 3 включен. В опции -trigraphs второй \? полезен в следующем примере:

printf("\?\?!\n");  

Вывод будет |, если ? не экранирован.

Для получения дополнительной информации о триграфе см. Cryptic line "??!??!" в устаревшем коде


Почему не выполняется экранирование ? работает нормально, там даже не предупреждение.

Потому что ? (и двойная кавычка ") могут быть представлены сами по себе стандартом:

C11 §6.4.4.4 Символьные константы Раздел 4

Двойная кавычка " и вопросительный знак ? представляются либо сами по себе, либо escape-последовательностями \" и \?, соответственно, но одинарная кавычка ' и обратная косая черта \ должны быть представлены соответственно управляющими последовательностями \' и \\.

Аналогично в С++:

С++ 11 §2.13.2 Символьные литералы Раздел 3

Некоторые неграфические символы, одинарная кавычка , двойная кавычка ", вопросительный знак ? и обратная косая черта \, могут быть представлены в соответствии с таблицей 6. Двойная кавычка " и знак вопроса ?, могут быть представлены как сами или управляющие последовательности \" и \? соответственно, но одинарная кавычка и обратная косая черта \ должны быть представлены escape-последовательностями \’ и \\ соответственно. Если символ, следующий за обратным слэшем, не является одним из указанных, поведение undefined. Управляющая последовательность задает один символ.