Trigraphs are nasty because they use sequences of characters that could legitimately appear within valid code. A common case that caused compiler errors for code for classic Macintosh:
unsigned int signature = '????';
Trigraph processing would turn it into:
unsigned int signature = '??^; /* Should be value 0x3F3F3F3F */
which, of course, will not compile. In some rarer cases, such processing could get code to be compiled, but with a different meaning from what was intended, for example,
char *template = "????/1234";
which will turn into
char *template = "??S4";
Not a string literal that was intended, but nonetheless completely legal.
In contrast, digraphs are relatively benign because, outside of some possible strange corner cases involving macros, no code containing processed digraphs would have a legitimate meaning if there was no such processing.
source share