TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

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

636 pointsby isomorphover 2 years ago

24 comments

susamover 2 years ago
I learnt C, more than 20 years ago, from the book <i>The C Programming Language</i> written by Brian W. Kernighan and Dennis M. Ritchie, also known as K&amp;R. I read the book almost cover to cover all the way from the preface at the beginning to its three appendices at the end while solving all the exercises that each chapter presented. As someone who knew very little about programming languages back then, this book was formative in my journey of becoming a programmer.<p>Appendix A (Reference Manual) of the book broadened my outlook on programming languages by providing me a glimpse of what goes into formally specifying a programming language. Section A.12 (Preprocessing) of this appendix specifies trigraph sequences. Quoting from the section:<p>&gt; Preprocessing itself takes place in several logically successive phases that may, in a particular implementation, be condensed.<p>&gt; 1. First, trigraph sequences as described in Par.A.12.1 are replaced by their equivalents. Should the operating system environment require it, newline characters are introduced between the lines of the source file.<p>Then section A.12.1 (Trigraph Sequences) further elaborates trigraph sequences in more detail. Quoting this section below:<p>&gt; The character set of C source programs is contained within seven-bit ASCII, but is a superset of the ISO 646-1983 Invariant Code Set. In order to enable programs to be represented in the reduced set, all occurrences of the following trigraph sequences are replaced by the corresponding single character. This replacement occurs before any other processing.<p><pre><code> ??= # ??&#x2F; \ ??&#x27; ^ ??( [ ??) ] ??! | ??&lt; { ??&gt; } ??- ~ </code></pre> &gt; No other such replacements occur.<p>&gt; Trigraph sequences are new with the ANSI standard.
评论 #33102637 未加载
评论 #33104594 未加载
评论 #33105161 未加载
评论 #33102990 未加载
评论 #33102399 未加载
评论 #33104776 未加载
评论 #33103290 未加载
bradfordover 2 years ago
Trigraphs make this obfuscated C submission possible: (<a href="https:&#x2F;&#x2F;gist.github.com&#x2F;Property404&#x2F;e31b99deb3527159e183" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;Property404&#x2F;e31b99deb3527159e183</a>)<p>I&#x27;ve pasted it here for convenience (formatting fixed, thanks child comment!):<p><pre><code> &#x2F;&#x2F; Are you there god??&#x2F; ??=define _(please, help) ??=define _____(i,m, v,e,r,y) r%:%:m ??=define ____ _____(a,f,r,a,i,d) main(__)&lt;%____(!_(-~-??-((-~-??-!__&lt;&lt;- ??-!!__)&lt;&lt;-??-(!!__&lt;&lt;!!__))+-~-~-??--~-~ -~-~-~-~-??-(-~-~-~-~-??-!!__&lt;&lt;-~!!__),- ??-!__))&lt;%??&gt;%&gt;_(__,___)??&lt;____ (printf(&quot;please let me die??&#x2F;r%d bottle%s&quot; &quot; of bee%s&quot;&quot;&quot;&quot;??&#x2F;n&quot;,(!(___ %-~-~!!___))?--__+!___++:__+!___++,!(__-!!___) &amp;&amp;___%-~-~!!___??!??!!(___%-~-~!!___??!??!__ -(-~!!___))?&quot;&quot;:&quot;s&quot;,___%-~-??-!!___&lt;-??-!!___? &quot;r on the wall&quot;:&quot;eeeeeeer! Take one down,pass ??&#x2F; it around&quot;)&amp;&amp;__&amp;&amp;_(__,___),&quot;mercy I&#x27;m in pain&quot;)??&lt;??&gt;??&gt;</code></pre>
评论 #33103785 未加载
评论 #33102321 未加载
评论 #33102967 未加载
评论 #33104591 未加载
rdlwover 2 years ago
See also: &quot;What is the &quot;--&gt;&quot; operator in C++?&quot;<p><a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;1642028" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;1642028</a>
评论 #33106238 未加载
评论 #33103026 未加载
评论 #33102522 未加载
layer8over 2 years ago
From the ASCII Wikipedia page (<a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;ASCII#7-bit_codes" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;ASCII#7-bit_codes</a>):<p>&gt; Almost every country needed an adapted version of ASCII, since ASCII suited the needs of only the US and a few other countries. For example, Canada had its own version that supported French characters.<p>&gt; Many other countries developed variants of ASCII to include non-English letters (e.g. é, ñ, ß, Ł), currency symbols (e.g. £, ¥), etc. See also YUSCII (Yugoslavia).<p>&gt; It would share most characters in common, but assign other locally useful characters to several code points reserved for &quot;national use&quot;. […]<p>&gt; Because the bracket and brace characters of ASCII were assigned to &quot;national use&quot; code points that were used for accented letters in other national variants of ISO&#x2F;IEC 646, a German, French, or Swedish, etc. programmer using their national variant of ISO&#x2F;IEC 646, rather than ASCII, had to write, and, thus, read, something such as<p><pre><code> ä aÄiÜ = &#x27;Ön&#x27;; ü </code></pre> instead of<p><pre><code> { a[i] = &#x27;\n&#x27;; } </code></pre> &gt; C trigraphs were created to solve this problem for ANSI C, although their late introduction and inconsistent implementation in compilers limited their use. Many programmers kept their computers on US-ASCII, so plain-text in Swedish, German etc. (for example, in e-mail or Usenet) contained &quot;{, }&quot; and similar variants in the middle of words, something those programmers got used to. For example, a Swedish programmer mailing another programmer asking if they should go for lunch, could get &quot;N{ jag har sm|rg}sar&quot; as the answer, which should be &quot;Nä jag har smörgåsar&quot; meaning &quot;No I&#x27;ve got sandwiches&quot;.
dhosekover 2 years ago
One of the challenges of | is that it was never entirely clear whether the ASCII | should be equivalent to EBCDIC’s | or ¦. As I recall, Waterloo C wanted ¦ as its vertical bar character, although I could be wrong. On the IBM system that I used back in the 80s, we had ASCII terminals which were run through a muxer to the actual system (which was part of the magic that allowed it to have thousands of concurrent users all getting real-time access—a lot of UI was offloaded to these systems which were essentially minicomputers on their own).
评论 #33103653 未加载
NegativeLatencyover 2 years ago
There&#x27;s also iso646.h which allows you to do some particularly python looking stuff:<p><pre><code> #include &lt;iso646.h&gt; #include &lt;stdbool.h&gt; #include &lt;stdio.h&gt; #define is == bool is_whitespace(int c) { if (c is &#x27; &#x27; or c is &#x27;\n&#x27; or c is &#x27;\t&#x27;) { return true; } return false; } int main() { int current, previous; bool in_word; while ((current = getchar()) not_eq EOF) { if (is_whitespace(current) and not is_whitespace(previous)) { putchar(&#x27;\n&#x27;); } else { putchar(current); } previous = current; } return 0; }</code></pre>
评论 #33102643 未加载
评论 #33119758 未加载
chromatinover 2 years ago
Wow, and I thought I knew C pretty well. Great post.<p>edited to add: I really like &quot;Modern C&quot; and just re-checked -- no mention of the preprocessor feature!<p><a href="https:&#x2F;&#x2F;hal.inria.fr&#x2F;hal-02383654&#x2F;file&#x2F;ModernC.pdf" rel="nofollow">https:&#x2F;&#x2F;hal.inria.fr&#x2F;hal-02383654&#x2F;file&#x2F;ModernC.pdf</a>
评论 #33102811 未加载
评论 #33102082 未加载
评论 #33102149 未加载
评论 #33103308 未加载
billpgover 2 years ago
&quot;There&#x27;s a problem. Some machines don&#x27;t have some braces and vertical bars and such. We&#x27;ll have to add keywords like OR and BEGIN and END.&quot;<p>&quot;Are question marks fine?&quot;<p>&quot;Yes.&quot;<p>&quot;I&#x27;ll come up with something.&quot;
评论 #33105925 未加载
cl3mischover 2 years ago
This reminds me of a comment on a Python discussion &gt;2 years ago, of which I think often:<p>&quot;Whether it&#x27;s computer languages or human ones, as soon as you get into a discussion about the correct parsing of a statement, you&#x27;ve lost and need to rewrite in a way that&#x27;s unambiguous. Too many people pride themselves on knowing more or less obscure rules and, honestly, no one else cares.&quot;<p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=23051202" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=23051202</a>
评论 #33106102 未加载
kbobover 2 years ago
I&#x27;d say, &quot;Congratulations! You&#x27;re one of today&#x27;s luck 10,000!&quot;, but trigraphs aren&#x27;t really much fun. Just another reminder that C is old, and computing is even older.<p>I&#x27;ve used uppercase-only terminals, and I&#x27;ve used ancient C, but not at the same time.
评论 #33103294 未加载
kenniskragover 2 years ago
trigraphs are removed in c++ 17<p><a href="https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;C%2B%2B17#Removed_features" rel="nofollow">https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;C%2B%2B17#Removed_features</a>
评论 #33102160 未加载
评论 #33102161 未加载
评论 #33102163 未加载
DonHopkinsover 2 years ago
Years ago I wrote a perfectly reasonable comment like &#x2F;* WTF??!?!!?!???? *&#x2F; and the old C compiler complained about &quot;invalid trigraph&quot;. A syntax error in the middle of a comment!<p>Took me a while to figure out that &quot;trigraph&quot; was referring to some part of &quot;??!?!!?!????&quot; and not &quot;WTF&quot;.
评论 #33106502 未加载
Agentlienover 2 years ago
Every time I hear about trigraphs I think of this horror:<p><a href="http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;53315710&#x2F;ddg#53315821" rel="nofollow">http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;53315710&#x2F;ddg#53315821</a>
FabHKover 2 years ago
There are two aspects to this, the trigraph, and using the short circuiting behaviour of the binary logic operator for control flow.<p>The latter is a very common idiom in Julia code, which I found obscure and puerile at first (“look how smart I am”), but have come to appreciate as concise and natural by now.<p>For example:<p><pre><code> function fact(n::Int) n &gt;= 0 || error(&quot;n must be non-negative&quot;) n == 0 &amp;&amp; return 1 n * fact(n-1) end </code></pre> <a href="https:&#x2F;&#x2F;docs.julialang.org&#x2F;en&#x2F;v1&#x2F;manual&#x2F;control-flow&#x2F;#Short-Circuit-Evaluation" rel="nofollow">https:&#x2F;&#x2F;docs.julialang.org&#x2F;en&#x2F;v1&#x2F;manual&#x2F;control-flow&#x2F;#Short-...</a>
divbzeroover 2 years ago
In addition to trigraphs, there are apparently a set of C alternative tokens defined as follows:<p><pre><code> #define and &amp;&amp; #define and_eq &amp;= #define bitand &amp; #define bitor | #define compl ~ #define not ! #define not_eq != #define or || #define or_eq |= #define xor ^ #define xor_eq ^= </code></pre> I suppose that allows for code like this:<p><pre><code> if (x or not y or not z) { return 1; } </code></pre> <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;C_alternative_tokens" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;C_alternative_tokens</a>
评论 #33106269 未加载
评论 #33110431 未加载
curling_gradover 2 years ago
Anecdote: An online judge website (which is pretty well known in Korea) has an easy problem[0] asking to write a program which adds &quot;??!&quot; to input. A lot of beginners&#x27; C&#x2F;C++ submissions got &quot;Wrong Answer&quot; verdict because of trigraphs.<p>[0]: <a href="https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;10926" rel="nofollow">https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;10926</a>
hgs3over 2 years ago
Reminds me of the &quot;goes to&quot; operator [1]<p>[1] <a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1642028&#x2F;what-is-the-operator-in-c" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1642028&#x2F;what-is-the-oper...</a>
cesarefover 2 years ago
This sort of practice goes back to BCPL, which wikipedia says is the first braced programming language. Because { and } weren&#x27;t universally available, compilers also supported the sequence $( and $) to represent these, which were typeable and printable on just about anything.<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;BCPL" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;BCPL</a><p>This is the earliest example of this sort of thing i&#x27;m aware of - is there an earlier example?<p>Also, BCPL supported &#x2F;&#x2F; for comments, again, probably the first use of this sequence.
virtualritzover 2 years ago
&gt; Has Microsoft Windows finally been open-sourced or where did this come from?<p>This comment on the SO post made my day. :D
anfractuosityover 2 years ago
In gcc I got:<p><pre><code> 1.c:1:11: warning: trigraph ??&lt; ignored, use -trigraphs to enable [-Wtrigraphs] </code></pre> Is there a preprocessor directive to enable support out of curiosity?
sargstuffover 2 years ago
from [1], trigraphs or not:<p><pre><code> int main() { [](){}() } </code></pre> is still wierd.<p>Wonder if there will be a request for an emacs macro to handle the replaced cpp trigraphs? [2]<p>[1] <a href="https:&#x2F;&#x2F;zygoloid.github.io&#x2F;cppcontest2018.html" rel="nofollow">https:&#x2F;&#x2F;zygoloid.github.io&#x2F;cppcontest2018.html</a> [2] <a href="https:&#x2F;&#x2F;www.emacswiki.org&#x2F;emacs&#x2F;CppTemplate" rel="nofollow">https:&#x2F;&#x2F;www.emacswiki.org&#x2F;emacs&#x2F;CppTemplate</a>
评论 #33106038 未加载
Waterluvianover 2 years ago
If we deprecated trigraphs and removed that step from the compiler would it speed compilation up much? I’m going to guess maybe by milliseconds?
评论 #33102557 未加载
评论 #33102430 未加载
评论 #33102408 未加载
评论 #33102664 未加载
chris_wotover 2 years ago
C++17 removed trigraphs. Sadly will no longer work.
评论 #33107030 未加载
olliejover 2 years ago
Oh trigraphs may you never die