28 ms·
What does the ??!??! operator do in C?
- chromatin 4y agoWow, and I thought I knew C pretty well. Great post. edited to add: I really like "Modern C" and just re-checked -- no mention of the preprocessor feature! https://hal.inria.fr/hal-02383654/file/ModernC.pdf https://hal.inria.fr/hal-02383654/file/ModernC.pdf
- richbell 4y agoI think C also has the elusive "down to" operator. https://stackoverflow.com/a/1642035 https://stackoverflow.com/a/1642035
- creativemonkeys 4y ago"-->" is not an operator in the C language, it's just a way of writing the unary operator "--" and comparison operator ">" together without any whitespace between them, since whitespace is ignored by the lexer.
- creativemonkeys 4y agoHave any of you downvoters read the C grammar? There is no --> operator in C. I'll never understand some people.
- richbell 4y agoI didn't downvote you but I presume others did because the StackOverflow post I linked to essentially says the same thing.
- deleted 4y ago[deleted]
- ryandrake 4y agoI think the only remaining purpose for trigraphs is when you are at the very end of a C interview, and your amazing candidate has answered every question perfectly, and you just have to find something they might not know about--only then do you reach for the trigraphs.
- thrwyoilarticle 4y agoGasp! You mean they've heard the volatile question before?
- sidewndr46 4y agoThe register keyword is far more interesting.
- Thorrez 4y agoHow about the restrict keyword.
- WithinReason 4y agoWow, I know all these. I only recently discovered bit addressing in C though.
- mpalczewski 4y agoWhy would you do this? Some weird insecurity?
- sirmoveon 4y agoSalary negotiating leverage? The worst they feel the more likely they accept to be lowballed
- ryandrake 4y agoHaha no! When a candidate is that awesome, I sometimes get morbidly curious about whether there is actually an end to that depth of knowledge or if it just goes on forever. At that point, they already have the "HIRE" classification and I'm pretty much in awe! I love it when a candidate blows through my easy, medium and hard questions and leaves me scrambling.
- Natsu 4y agoHonestly, I thought this was about a programming language called C? rather than C.
- rdlw 4y agoIn the spirit of C++ and C#, there could be a C?'1':'0'
- kenniskrag 4y agotrigraphs are removed in c++ 17 https://en.m.wikipedia.org/wiki/C%2B%2B17#Removed_features https://en.m.wikipedia.org/wiki/C%2B%2B17#Removed_features
- amelius 4y agoI've never seen them used anywhere.
- Rebelgecko 4y agoThey're good for obfuscating source code but AFAICT that's about it on modern machines
- sargstuff 4y agoLess obscure if physical print type head doesn't have the corresponding trigraph representation. Unicode is a worthy successor to trigraphs -- no need for pre-processing! Guess with tri-graph elimination & awk getting unicode support will have to gawk C with cpp using pipology theory. But think the cpp has to go away first, after enough sed. https://grayson.sh/blogs/using-piphilology-to-hide-strings https://grayson.sh/blogs/using-piphilology-to-hide-strings https://www.gnu.org/software/gawk/manual/gawk.html#Signature-Program https://www.gnu.org/software/gawk/manual/gawk.html#Signature...
- mfost 4y agoThey were meant for coding C on machines that had even less than ASCII as available text encoding really. So no wonder you never see them.
- shakna 4y agoThey were meant, mostly, for punch-card machines. So if you started programming anywhere after the point in time when you needed to hand off your code to a punch card operator, you're unlikely to have seen them.
- 4y ago
- rdlw 4y agoSee also: "What is the "-->" operator in C++?" https://stackoverflow.com/q/1642028 https://stackoverflow.com/q/1642028
- teawrecks 4y agoYeah, I thought this was going to involve the ternary operator. TIL about trigraphs.
- sargstuff 4y agostill can, just have to add precidence changing characters ( )
- LorenPechtel 4y agoYeah, C# has some shortcuts these days of the form x <symbol>= y that compile as x = x <symbol> y. They are an actual advantage as x only needs to be stated once and it is absolutely clear that is assignment into the value--more information readily communicated with fewer characters. It also has the null coalescing operator ??. Put those together and you can have x ??= y (if (x = null) x = y;)--useful for lazy initialization and it can be returned, making lazy initialization getters much clearer. This looked awfully similar, I was trying to figure out how you could negate null coalescing.
- pjmlp 4y agoThese days, like since C# 1.0.
- tuukkah 4y agoIt's interesting to see the history of any given piece of syntax. This specific one is called augmented assignment or compound assignment: https://en.wikipedia.org/wiki/Augmented_assignment https://en.wikipedia.org/wiki/Augmented_assignment +:= in Algol68 =+ in B += in C
- furyofantares 4y ago
- bradford 4y agoTrigraphs make this obfuscated C submission possible: (https://gist.github.com/Property404/e31b99deb3527159e183 https://gist.github.com/Property404/e31b99deb3527159e183) I've pasted it here for convenience (formatting fixed, thanks child comment!): // Are you there god??/ ??=define _(please, help) ??=define _____(i,m, v,e,r,y) r%:%:m ??=define ____ _____(a,f,r,a,i,d) main(__)<%____(!_(-~-??-((-~-??-!__<<- ??-!!__)<<-??-(!!__<<!!__))+-~-~-??--~-~ -~-~-~-~-??-(-~-~-~-~-??-!!__<<-~!!__),- ??-!__))<%??>%>_(__,___)??<____ (printf("please let me die??/r%d bottle%s" " of bee%s""""??/n",(!(___ %-~-~!!___))?--__+!___++:__+!___++,!(__-!!___) &&___%-~-~!!___??!??!!(___%-~-~!!___??!??!__ -(-~!!___))?"":"s",___%-~-??-!!___<-??-!!___? "r on the wall":"eeeeeeer! Take one down,pass ??/ it around")&&__&&_(__,___),"mercy I'm in pain")??<??>??>
- thamer 4y agoHow to format text on HN: https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc For code blocks, prefix each line with two or more spaces.
- eek2121 4y agoThanks (I haven't seen this despite lurking on HN for 'a long time' and interacting with it recently, however, you clearly didn't quote the doc, which says Text after a blank line that is indented by two or more spaces is reproduced verbatim. (This is intended for code.) Small nitpick, however I am happy you linked the page.
- sargstuff 4y agoGuess with tri-graph elimination & awk getting unicode support will have to gawk C with cpp using pipology theory. But think the cpp has to go away first, after enough sed. https://grayson.sh/blogs/using-piphilology-to-hide-strings https://grayson.sh/blogs/using-piphilology-to-hide-strings https://www.gnu.org/software/gawk/manual/gawk.html#Signature https://www.gnu.org/software/gawk/manual/gawk.html#Signature...
- omoikane 4y agoRoughly the only good use of trigraphs these days is for obfuscated code, for example here: https://www.ioccc.org/years.html#1990_scjones https://www.ioccc.org/years.html#1990_scjones But trigraphs have gotten old even for IOCCC. In the guidelines for recent years, they specifically mention "We tend to dislike programs that ... obfuscate by excessive use of ANSI tri-graphs": https://www.ioccc.org/2020/guidelines.txt https://www.ioccc.org/2020/guidelines.txt
- susam 4y agoI learnt C, more than 20 years ago, from the book The C Programming Language written by Brian W. Kernighan and Dennis M. Ritchie, also known as K&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. 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: > Preprocessing itself takes place in several logically successive phases that may, in a particular implementation, be condensed. > 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. Then section A.12.1 (Trigraph Sequences) further elaborates trigraph sequences in more detail. Quoting this section below: > 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. ??= # ??/ \ ??' ^ ??( [ ??) ] ??! | ??< { ??> } ??- ~ > No other such replacements occur. > Trigraph sequences are new with the ANSI standard.
- Taniwha 4y agoThis is because IBM 029 card punches don't support these characters right?
- Waterluvian 4y agoIf we deprecated trigraphs and removed that step from the compiler would it speed compilation up much? I’m going to guess maybe by milliseconds?
- zik 4y agoProbably not by any measurable amount
- quickthrower2 4y agoI imagine microseconds or less
- sargstuff 4y ago0 if sed used to expand the trigraphs before passing output to cpp/compiler.
- quickthrower2 4y agoAlways zero if you make it someone else’s problem :-)
- pantalaimon 4y agoThey are already deprecated and removed in C23
- NavinF 4y agomicroseconds, not milliseconds
- dhosek 4y agoOne 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).
- watersb 4y agoGreat article (that appeared on HN somewhat recently) from Ken Shirrif on the history display terminals, and a great photo of the IBM 2848 Display Controller. http://www.righto.com/2019/11/ibm-sonic-delay-lines-and-history-of.html http://www.righto.com/2019/11/ibm-sonic-delay-lines-and-hist... The next-gen was far more common.. The IBM 3270 terminal hooked to a local controller that talked to the mainframe. Could also hook a printer to the controller, you could print screen and simple forms independently from the mainframe. You know all this, but I've always thought it was cool, and try to refresh my understanding of the setup. I no doubt have many details wrong.
- NegativeLatency 4y agoThere's also iso646.h which allows you to do some particularly python looking stuff: #include <iso646.h> #include <stdbool.h> #include <stdio.h> #define is == bool is_whitespace(int c) { if (c is ' ' or c is '\n' or c is '\t') { 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('\n'); } else { putchar(current); } previous = current; } return 0; }
- garaetjjte 4y agoOf course when you are willing to use preprocessor, you can do things like Bournegol: http://oldhome.schmorp.de/marc/bournegol.html http://oldhome.schmorp.de/marc/bournegol.html
- sargstuff 4y agoOr give C C++ functionality : https://libcello.org/ https://libcello.org/
- sargstuff 4y agoor throw exceptional loops : https://www.chiark.greenend.org.uk/%7Esgtatham/mp/ https://www.chiark.greenend.org.uk/%7Esgtatham/mp/
- sargstuff 4y agohttps://github.com/Hirrolot/metalang99 https://github.com/Hirrolot/metalang99
- gpderetta 4y agoIn C++ these are genuine operators and do not require the macros from iso646. I quite like them, but then again, I have been writing way too much python lately.
- hgs3 4y agoReminds me of the "goes to" operator [1] [1] https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c https://stackoverflow.com/questions/1642028/what-is-the-oper...
- olliej 4y agoOh trigraphs may you never die
- kbob 4y agoI'd say, "Congratulations! You're one of today's luck 10,000!", but trigraphs aren't really much fun. Just another reminder that C is old, and computing is even older. I've used uppercase-only terminals, and I've used ancient C, but not at the same time.
- WalterBright 4y agoAncient C didn't have trigraphs. My copy of K+R (1978) doesn't mention them.
- kragen 4y agoNo, they were a design error introduced by the ANSI committee.
- krylon 4y agoI thought ISO added them when C went from ANSI C (1989) to ISO C (1990), along with wchar.h and such. I might misremember, though, it's been a long time since I did anything serious with C. Come to think of it, didn't they remove trigraphs in one of the more recent iterations of the standard?
- kragen 4y agoThey did remove trigraphs in one of the more recent iterations. It's possible that it was as you say, but I have this vague memory that it was ANSI who added them. I think maybe what the ISO added were https://en.wikipedia.org/wiki/C_alternative_tokens https://en.wikipedia.org/wiki/C_alternative_tokens.
- sargstuff 4y agofrom [1], trigraphs or not: int main() { [](){}() } is still wierd. Wonder if there will be a request for an emacs macro to handle the replaced cpp trigraphs? [2] [1] https://zygoloid.github.io/cppcontest2018.html https://zygoloid.github.io/cppcontest2018.html [2] https://www.emacswiki.org/emacs/CppTemplate https://www.emacswiki.org/emacs/CppTemplate
- planede 4y agoGood news, in C++20 you can add <> there somewhere, although probably it can't be empty. Anyway, probably obscure enough: int main() { []<class=void>(){}(); }
- layer8 4y agoFrom the ASCII Wikipedia page (https://en.wikipedia.org/wiki/ASCII#7-bit_codes https://en.wikipedia.org/wiki/ASCII#7-bit_codes): > 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. > Many other countries developed variants of ASCII to include non-English letters (e.g. é, ñ, ß, Ł), currency symbols (e.g. £, ¥), etc. See also YUSCII (Yugoslavia). > It would share most characters in common, but assign other locally useful characters to several code points reserved for "national use". […] > Because the bracket and brace characters of ASCII were assigned to "national use" code points that were used for accented letters in other national variants of ISO/IEC 646, a German, French, or Swedish, etc. programmer using their national variant of ISO/IEC 646, rather than ASCII, had to write, and, thus, read, something such as ä aÄiÜ = 'Ön'; ü instead of { a[i] = '\n'; } > 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 "{, }" 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 "N{ jag har sm|rg}sar" as the answer, which should be "Nä jag har smörgåsar" meaning "No I've got sandwiches".
- deleted 4y ago[deleted]
- FabHK 4y agoThere are two aspects to this, the trigraph, and using the short circuiting behaviour of the binary logic operator for control flow. 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. For example: function fact(n::Int) n >= 0 || error("n must be non-negative") n == 0 && return 1 n * fact(n-1) end https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation https://docs.julialang.org/en/v1/manual/control-flow/#Short-...
- Agentlien 4y agoEvery time I hear about trigraphs I think of this horror: http://stackoverflow.com/questions/53315710/ddg#53315821 http://stackoverflow.com/questions/53315710/ddg#53315821
- cesaref 4y agoThis sort of practice goes back to BCPL, which wikipedia says is the first braced programming language. Because { and } weren't universally available, compilers also supported the sequence $( and $) to represent these, which were typeable and printable on just about anything. https://en.wikipedia.org/wiki/BCPL https://en.wikipedia.org/wiki/BCPL This is the earliest example of this sort of thing i'm aware of - is there an earlier example? Also, BCPL supported // for comments, again, probably the first use of this sequence.
- curling_grad 4y agoAnecdote: An online judge website (which is pretty well known in Korea) has an easy problem[0] asking to write a program which adds "??!" to input. A lot of beginners' C/C++ submissions got "Wrong Answer" verdict because of trigraphs. [0]: https://www.acmicpc.net/problem/10926 https://www.acmicpc.net/problem/10926
- billpg 4y ago"There's a problem. Some machines don't have some braces and vertical bars and such. We'll have to add keywords like OR and BEGIN and END." "Are question marks fine?" "Yes." "I'll come up with something."
- daptaq 4y agoSee iso646.h, and https://en.cppreference.com/w/c/language/operator_alternative https://en.cppreference.com/w/c/language/operator_alternativ....
- chris_wot 4y agoC++17 removed trigraphs. Sadly will no longer work.
- omnicognate 4y agos/Sadly/Gladly/
- cl3misch 4y agoThis reminds me of a comment on a Python discussion >2 years ago, of which I think often: "Whether it's computer languages or human ones, as soon as you get into a discussion about the correct parsing of a statement, you've lost and need to rewrite in a way that's unambiguous. Too many people pride themselves on knowing more or less obscure rules and, honestly, no one else cares." https://news.ycombinator.com/item?id=23051202 https://news.ycombinator.com/item?id=23051202
- halileohalilei 4y agoCompletely agree with that. In fact, it's the first thing I thought of when I saw the code snippet in question. Even if you replace the trigraph with the regular || operator, it's still hard to read that piece of code. Syntactic sugars and short circuits are cool and all but most of the time they have no place in production code that's meant to be read by other developers.
- divbzero 4y agoIn addition to trigraphs, there are apparently a set of C alternative tokens defined as follows: #define and && #define and_eq &= #define bitand & #define bitor | #define compl ~ #define not ! #define not_eq != #define or || #define or_eq |= #define xor ^ #define xor_eq ^= I suppose that allows for code like this: if (x or not y or not z) { return 1; } https://en.wikipedia.org/wiki/C_alternative_tokens https://en.wikipedia.org/wiki/C_alternative_tokens
- pwdisswordfish9 4y agoMakes for great obfuscated C++. template <typename T> void print(T const bitand foo) { std::cout << foo << std::endl; }
- pjmlp 4y agovoid print(auto const bitand foo) { std::cout << foo << std::endl; } Since C++20.
- pavon 4y agoThe instructor at the branch college where I learned C++ in the late 90's taught us that those were the preferred operators and that the old operators belonged in the wastebasket of history along with printf and str* functions. It made for some amusing group projects when I got to university, when classmates had never seen those operators and were trying to figure out where they were coming from and why I would write such silly things. I trolled them by replacing all my brackets with `begin` and `end` in the next assignment before moving to the standard use of C operators for the rest of the class.
- virtualritz 4y ago> Has Microsoft Windows finally been open-sourced or where did this come from? This comment on the SO post made my day. :D
- DonHopkins 4y agoYears ago I wrote a perfectly reasonable comment like /* WTF??!?!!?!???? */ and the old C compiler complained about "invalid trigraph". A syntax error in the middle of a comment! Took me a while to figure out that "trigraph" was referring to some part of "??!?!!?!????" and not "WTF".
- hvdijk 4y agoThat's a bug, there is no such thing as an invalid trigraph. ?? followed by any character other than =, /, ', (, ), !, <, >, or - is not a valid trigraph, but that doesn't make it an invalid trigraph, that just makes it not a trigraph, it's perfectly valid to have ??? in a comment, or in a string literal.
- DonHopkins 4y agoAre you telling me that C compilers in the early 90's had bugs and confusing error messages??!!?!??? WTF?!??!?!?
- benj111 4y agoOh so that's why their called trigraphs, because there's 3 valid states? Valid Invalid ??? (Exercise for the reader to decide if this is a trigraph or not)
- jawadch93 4y ago[dead]
- anfractuosity 4y agoIn gcc I got: 1.c:1:11: warning: trigraph ??< ignored, use -trigraphs to enable [-Wtrigraphs] Is there a preprocessor directive to enable support out of curiosity?