Як вже говорилося ??!??!
, по суті , два тріграфи ( ??!
і ??!
знову) mushed разом , які замінюються переведений на ||
, тобто логічне АБО , препроцесором.
Наступна таблиця, що містить кожен триграф, повинна допомогти розмежувати альтернативні комбінації триграфа:
Trigraph Replaces
??( [
??) ]
??< {
??> }
??/ \
??' ^
??= #
??! |
??- ~
Джерело: C: Довідковий посібник 5-е видання
Отже, триграф, схожий ??(??)
, з часом відобразиться []
, ??(??)??(??)
заміниться [][]
і так далі, ви отримаєте ідею.
Оскільки триграфи підміняються під час попередньої обробки, ви можете використати, cpp
щоб самостійно переглянути результат, використовуючи нерозумну trigr.c
програму:
void main(){ const char *s = "??!??!"; }
і обробляти його за допомогою:
cpp -trigraphs trigr.c
Ви отримаєте консольний вихід
void main(){ const char *s = "||"; }
Як ви можете помітити, опцію -trigraphs
потрібно вказати, інакше cpp
винесете попередження; це вказує на те, як триграфи - це минуле і не має жодної сучасної цінності, окрім заплутування людей, які можуть наткнутися на них .
Що стосується обґрунтування введення триграфа, то його краще зрозуміти, переглядаючи розділ історії ISO / IEC 646 :
ISO / IEC 646 та його попередник ASCII (ANSI X3.4) значною мірою схвалили існуючу практику щодо кодування символів у телекомунікаційній галузі.
Оскільки ASCII не надав кількість символів, необхідних для інших мов, крім англійської, було створено ряд національних варіантів, які замінювали деякі менш вживані символи потрібними .
(наголос мій)
Отже, по суті, деякі необхідні персонажі (ті, для яких існує триграф) були замінені в певних національних варіантах. Це призводить до поперемінного подання за допомогою триграфа, що складається з символів, які інші варіанти все ще мали навколо.
!ErrorHasOccurred() ??!???! HandleError();
компілювати? Ось так??!
???
!
. Доводить суть?