Categories
c operators trigraphs

What does the ??!??! operator do in C?

2280

I saw a line of C that looked like this:

!ErrorHasOccured() ??!??! HandleError();

It compiled correctly and seems to run ok. It seems like it’s checking if an error has occurred, and if it has, it handles it. But I’m not really sure what it’s actually doing or how it’s doing it. It does look like the programmer is trying express their feelings about errors.

I have never seen the ??!??! before in any programming language, and I can’t find documentation for it anywhere. (Google doesn’t help with search terms like ??!??!). What does it do and how does the code sample work?

4

  • 37

    Sadly this gem of a program won’t work in C++17 and newer.

    – phoenix

    Jul 15, 2018 at 12:40

  • 5

    Of course, this is only half the fun unless the symbols are named wtf and roflmao, respectively.

    Feb 27 at 8:36

  • 4

    i am going to use this to annoy humans

    – tycoon

    Mar 16 at 12:40

  • Has Microsoft Windows finally been open-sourced or where did this come from?

    – Fonic

    Aug 1 at 13:46

1805

??! is a trigraph that translates to |. So it says:

!ErrorHasOccured() || HandleError();

which, due to short circuiting, is equivalent to:

if (ErrorHasOccured())
    HandleError();

Guru of the Week (deals with C++ but relevant here), where I picked this up.

Possible origin of trigraphs or as @DwB points out in the comments it’s more likely due to EBCDIC being difficult (again). This discussion on the IBM developerworks board seems to support that theory.

From ISO/IEC 9899:1999 §5.2.1.1, footnote 12 (h/t @Random832):

The trigraph sequences enable the input of characters that are not defined in the Invariant Code Set as
described in ISO/IEC 646, which is a subset of the seven-bit US ASCII code set.

7

  • 467

    Trigraphs originally were needed in case you keyboard didn’t have eg a ‘|’ symbol. Here it’s either the programmer deliberately being annoying or some bizarre editor ‘feature’

    Oct 19, 2011 at 17:02


  • 31

    It’s not necessarily EBCDIC – the set of characters that require trigraphs almost exactly matches the set of characters that are not invariant in ISO-646 (i.e. the old ‘national ascii’ standards).

    – Random832

    Oct 19, 2011 at 18:01

  • 80

    A perfectly readable alternative would be ErrorHasOccurred() && HandleError(); That is, if you’re used to shell scripting. 🙂

    Oct 24, 2011 at 15:01

  • 11

    Just note that many coding standards specifically ban the use of Trigraphs and Digraphs, and many compilers & static analyzers will flag their use.

    – Luciano

    Apr 15, 2015 at 15:35

  • 8

    Not valid since C++17 😐

    Dec 15, 2018 at 17:12

527

Well, why this exists in general is probably different than why it exists in your example.

It all started half a century ago with repurposing hardcopy communication terminals as computer user interfaces. In the initial Unix and C era that was the ASR-33 Teletype.

This device was slow (10 cps) and noisy and ugly and its view of the ASCII character set ended at 0x5f, so it had (look closely at the pic) none of the keys:

{ | } ~ 

The trigraphs were defined to fix a specific problem. The idea was that C programs could use the ASCII subset found on the ASR-33 and in other environments missing the high ASCII values.

Your example is actually two of ??!, each meaning |, so the result is ||.

However, people writing C code almost by definition had modern equipment,1 so my guess is: someone showing off or amusing themself, leaving a kind of Easter egg in the code for you to find.

It sure worked, it led to a wildly popular SO question.

ASR-33 Teletype

                                            ASR-33 Teletype


1. For that matter, the trigraphs were invented by the ANSI committee, which first met after C become a runaway success, so none of the original C code or coders would have used them.

13

  • 28

    It’s not the only case of missing characters, in the keyboard and the character set. The Commodore 64 is likely to be more familiar to a lot of people in their late thirties and upwards – the displayed character sets both lacked braces (and probably the bar and tilde too) – in this case because the “ASCII” wasn’t ASCII. In ECMA-6 (almost always called ASCII, but not US-ASCII) there were 18 region-specific codes, but I don’t know which codes they were. The one thing I can say for sure – in the British “ASCII”, # was replaced with £. In other regions, maybe “ASCII” had no braces etc.

    – user180247

    Oct 20, 2011 at 4:06

  • 8

    The similar ATASCII character set for Atari 8-bit computers also lacked { } as well as ~ and `.

    – dan04

    Oct 20, 2011 at 6:16


  • 53

    See these two Wikipedia articles. I’m just about old enough to still remember the era of 7-bit national charsets (although I’m sure they still linger on in some dark unswept corners), and the book I first learned C from found it necessary to warn about the possibility of if (x || y) { a[i] = '\0'; } looking like if (x öö y) ä aÄiÅ = 'Ö0'; å in the wrong charset.

    Oct 20, 2011 at 13:36

  • 14

    Another interesting historical note is that Unix (which was the big platform C rode in on) may have been the first system of any significance (and maybe the first overall) to default alphabetic values to lower case rather than upper case. Although I haven’t seen with my own eyes many contemporary systems, I think this was a real sign of sophistication. Besides being really the only decent OS, Unix also converted your upper case to lower, rather than vice versa. Those guys were really cool.

    Oct 26, 2011 at 2:45


  • 25

    Funny story I gotta tell ya… the IBM RS/6000 workstation’s XL Fortran compiler was developed from the XL C compiler. In the first few releases, they accidentally left in the trigraph processing, so there were some legit Fortran character sequences (in a literal string, IIRC) that were misinterpreted as C trigraphs, leading to some interesting bugs!

    Apr 11, 2014 at 18:25


191

It’s a C trigraph. ??! is |, so ??!??! is the operator ||

3

  • 13

    trigraph come from a period where some keyboard didnt have all the keys they have now. It also hels when some text editor reserved special characters for special things. It’s mostly a relic of the past and a quizz enabler 😉

    Mar 23, 2017 at 19:45

  • 6

    Because some keyboards apparently don’t have “|” so some people have no option but to headbutt the keyboard repeatedly until a trigraph occurs that gives them the symbols they need.

    – Owl

    Jan 11, 2019 at 18:06

  • 3

    And then there is the <iso646.h> header file.

    Oct 25, 2019 at 21:08