[HN Gopher] What does the ??!??! operator do in C?
___________________________________________________________________
What does the ??!??! operator do in C?
Author : isomorph
Score : 600 points
Date : 2022-10-05 21:24 UTC (1 days ago)
(HTM) web link (stackoverflow.com)
(TXT) w3m dump (stackoverflow.com)
| billpg wrote:
| "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 wrote:
| See iso646.h, and https://en.cppreference.com/w/c/language/oper
| ator_alternativ....
| rdlw wrote:
| See also: "What is the "-->" operator in C++?"
|
| https://stackoverflow.com/q/1642028
| falcor84 wrote:
| And of course, its cousin the slides-to operator, described in
| the answer https://stackoverflow.com/a/8909176/493553 with the
| following example: while (x --\
| \ \ \
| > 0) printf("%d ", x);
| DonHopkins wrote:
| Whenever somebody complains about how Python uses indentation
| instead of { } or BEGIN END, you can prove to them that it
| actually does support that and more, by demonstrating that
| they simply need to prefix their favorite brackets or
| keywords with Python's unary "#" operator, like:
| for i in range(10): #{ print(i) #}
|
| or: for i in range(10): #BEGIN
| print(i) #END
|
| You can even mix-and-match them, like: for
| i in range(10): #BEGIN print(i) #}
|
| or: for i in range(10): #{
| print(i) #END
|
| or turn them inside-out, like: for i in
| range(10): #} print(i) #{
|
| or: for i in range(10): #END
| print(i) #BEGIN
|
| Python is extremely flexible that way, and can easily
| strangle and eat all other languages.
| paulluuk wrote:
| Ha, I chuckled
| ajoseps wrote:
| I mean that's fine for code that you write, but most python
| code is not like that at all
| furyofantares wrote:
| And sort of the opposite of that, I once had someone say they
| wanted to contribute to the C++ portion of our codebase, but
| the only problem was they didn't know how to make the "->"
| character, and did they need to get a special keyboard?
| icambron wrote:
| Is it possible that their editor provided ligatures but they
| didn't know about those and so assumed it was actually a
| character in the source?
| furyofantares wrote:
| No, it was much too long ago for that. They were just very
| new to programming and had interpreted it wrong the first
| time they saw it (most likely in a book, that's how we used
| to get our first introduction to a language).
| Izkata wrote:
| Semi-related: One of the people on my team uses a font that
| displays things like ">=" as ">=". I was a bit confused the
| first time I saw it.
| teawrecks wrote:
| Yeah, I thought this was going to involve the ternary operator.
| TIL about trigraphs.
| LorenPechtel wrote:
| Yeah, 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 wrote:
| These days, like since C# 1.0.
| tuukkah wrote:
| It'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
|
| +:= in Algol68
|
| =+ in B
|
| += in C
| sargstuff wrote:
| still can, just have to add precidence changing characters (
| )
| hgs3 wrote:
| Reminds me of the "goes to" operator [1]
|
| [1] https://stackoverflow.com/questions/1642028/what-is-the-
| oper...
| cl3misch wrote:
| This 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
| halileohalilei wrote:
| Completely 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.
| chris_wot wrote:
| C++17 removed trigraphs. Sadly will no longer work.
| omnicognate wrote:
| s/Sadly/Gladly/
| anfractuosity wrote:
| In 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?
| olliej wrote:
| Oh trigraphs may you never die
| Agentlien wrote:
| Every time I hear about trigraphs I think of this horror:
|
| http://stackoverflow.com/questions/53315710/ddg#53315821
| FabHK wrote:
| There 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-...
| bradford wrote:
| Trigraphs make this obfuscated C submission possible:
| (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")??<??>??>
| sargstuff wrote:
| 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://www.gnu.org/software/gawk/manual/gawk.html#Signature...
| omoikane wrote:
| Roughly the only good use of trigraphs these days is for
| obfuscated code, for example here:
| 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
| lifthrasiir wrote:
| Note that this uses not only trigraphs but also digraphs (here
| `<%`, `%>` and `%:`), which are similar to trigraphs in
| intended usages but behave much differently to digraphs in that
| it is a proper token and not a preprocessor substitution
| pattern. `printf("??(foo??)<:bar:>%c", "quux"<:1:>)` prints
| `[foo]<:bar:>u`, for example. Therefore digraphs are deemed
| less dangerous (however obscure) than trigraphs and do not
| require any compiler options.
| DonHopkins wrote:
| Bjarne Stroustrup proposed Generalized Overloading for
| C++2000, which not only lets you override all kinds of white
| space, like between two symbols separated left to right by a
| space (i.e. "a b" to add a to b), or two symbols separated
| top to bottom by a newline (i.e. "a \n b" to divide a by b,
| like a fraction), or even by tabs, or either kind of comment,
| but it also lets you override writing two symbols next to
| each other without any separation (i.e. "ab" to multiply a by
| b, which mathematicians love)!
|
| Of course they also had to limit the number of characters per
| symbol to 1 in order to unambiguously support the "ab" syntax
| for multiplying a and b (or however you wanted to overload
| the "absence of white space" operator), but fortunately they
| mitigated that little problem by making C++ fully supports
| Unicode, so you had thousands of single character Unicode
| variable names to choose from. His prophetic intuition was
| spot-on, now that there are so many expressive and inclusive
| Emoji characters to use for single character variable names!
|
| https://www.stroustrup.com/whitespace98.pdf
|
| I really appreciate Bjarne Stroustrup's clean simple design
| and coherent long term vision for C++2000, and I'm looking
| forward to using three dimensional white space overloading in
| C++3D.
| ralphb wrote:
| I am almost unhappy to learn that this was a joke. Would
| have been nice to put a final (personal) nail in the C++
| coffin with this insanity. However, I guess it says enough
| that I did have to dig quite far into the paper to realize
| whether Bjarne was joking or not.
| thamer wrote:
| How to format text on HN:
| https://news.ycombinator.com/formatdoc For code
| blocks, prefix each line with two or more spaces.
| eek2121 wrote:
| Thanks (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.
| kbob wrote:
| I'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 wrote:
| Ancient C didn't have trigraphs. My copy of K+R (1978) doesn't
| mention them.
| kragen wrote:
| No, they were a design error introduced by the ANSI
| committee.
| layer8 wrote:
| From the ASCII Wikipedia page
| (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. e, n, ss, L), currency symbols (e.g.
| PS, Y=), 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 aAiU = 'On'; u
|
| 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 "Na jag har
| smorgasar" meaning "No I've got sandwiches".
| divbzero wrote:
| In 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
| pwdisswordfish9 wrote:
| Makes for great obfuscated C++. template
| <typename T> void print(T const bitand foo) {
| std::cout << foo << std::endl; }
| pjmlp wrote:
| void print(auto const bitand foo) { std::cout <<
| foo << std::endl; }
|
| Since C++20.
| pavon wrote:
| The 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.
| susam wrote:
| I 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.
| usr1106 wrote:
| In 1990 IBM donated a 9370 computer to our university. The
| default code page for German EBCDIC did not support square
| brackets.
|
| I don't remember whether trigraphs were not supported by the
| compiler at the time or whether we just wanted to avoid
| completely unreadable code. Not experienced in VM/370
| administration we spent weeks to modify the system to use some
| international EBCDIC codepage.
|
| The system never saw much use, everybody preferred Unix
| workstations where programming in C was a natural thing.
| vonwoodson wrote:
| To be fair, and definitely a part of its appeal, the K&R is
| only 312 pages long. It covers the language and most of the
| standard library you'll need.
|
| As opposed to say, "Learn You a Haskell for Great Good! A
| Beginner's Guide" which is 881 pages and doesn't even
| moderately cover the prelude.
|
| Anyway, C is an amazing language and I keep a K&R on my phone
| as a pdf
| 1-more wrote:
| My copy of Learn You a Haskell ends on page 360 and the index
| is another 16 pages. Is this some weirdly shaped PDF of it
| with tiny phone-sized pages?
| vonwoodson wrote:
| Could be, now that you mention it. Which, now, makes me
| wonder if my K&R is even shorter.
| zh3 wrote:
| Just checked my first edition K&R (copyright date 1978,
| last page number is 228 (end of index) after which there
| is a single tearout page for other "High Quality C and
| Unix system titles" from Prentice Hall. There's also a
| front section that has about 10 pages in roman numerals
| (2 pages of prefix starting with 'ix') so about 240 pages
| total.
|
| Page 1 starts: "Chapter 0: Introduction".
| checkyoursudo wrote:
| Page 1? What, it's not zero indexed?
| DonHopkins wrote:
| It looks like it's 1-indexed, but it core dumps when you
| get to the last page.
| DonHopkins wrote:
| There's one thing that's usually true about every well
| used copy of K&R, and that's that it always opens up
| easily and by default to the page with the huge operator
| precedence order and associativity table, because that's
| the page everyone needs to refer to the most often, which
| is usually bookmarked, but in an old copy doesn't even
| need to be.
|
| That says something about the C programming language
| design, that I as a deeply stack based FORTH programmer
| and explicitly parenthetical LISP programmer find
| horrible.
| benj111 wrote:
| Isn't that what brackets are for?
|
| Well that's what I do. If you're having to look it up to
| write it, you're going to have to look it up to read it
| again down the line.
| belter wrote:
| Can I up vote for first paragraph, and down vote the
| second? :-)
| dahfizz wrote:
| Just use parentheses if you're doing many operations on
| one line? This is common sense in any programming
| language.
|
| I've been programming in C for years and never had an
| issue with operator precedence.
| coldpie wrote:
| I agree, but I'm still cracking open that page when I'm
| reading someone else's code. I guess you work solo most
| of the time?
| dahfizz wrote:
| Nope, I work on a team. I guess we all have similar
| instincts about what is readable.
| mrguyorama wrote:
| I don't know what it is with C programmers and
| programming "terseness". It hasn't been the 60s since the
| 60s, and you have gobs of memory available, your source
| code can have syntactic sugar for the purpose of
| readability and the world won't end.
| dahfizz wrote:
| Can you give an example of syntactic sugar in a modern
| language that makes order of operations a non-issue?
| rdlw wrote:
| Parentheses
| dahfizz wrote:
| Yeah, that's why I said
|
| > Just use parentheses
|
| Not sure what that has to do with memory usage..?
| rdlw wrote:
| Just to clarify, I'm not the original person you replied
| to, and we all agree about using parentheses.
|
| mrguyorama just implied that the only reason you would
| check the operator precedence chart would be to shave a
| few bytes off the size of your source code, which has not
| been a reasonable reason to do anything for many decades,
| and yet C programmers seem to like to do it anyway.
| falcrist wrote:
| There's a lot of exaggeration that goes on with certain
| fans of postfix systems when they talk about infix
| systems.
|
| For example: I really like HP calculators, so I'm in
| several facebook groups for fans of RPN/RPL and HP
| specifically. Sometimes a few of them go way too far out
| of their way to try to demonstrate how inferior algebraic
| systems must be.
|
| For the record, my copy of K&R wants to open into either
| section 7.6 or appendix B. No idea what this says about
| me, though.
| DonHopkins wrote:
| It's not that YOU have any issues with it -- because
| you're perfect.
|
| https://www.youtube.com/watch?v=fKHaNIEa6kA
|
| It's about the poor people who read your code that relies
| on both you and them having perfectly memorized every
| single little detail of operator precedence and
| associativity, instead of simply and consistently using
| parenthesis.
|
| Quick without looking: can you tell me what the
| precedence and associativity of the ternary ?: operator
| is?
|
| The designer of PHP got it wrong (which isn't surprising
| given his proudly self proclaimed contempt towards
| computer science and incompetence at parser writing), but
| then millions of PHP programmers also learned it the
| wrong way.
|
| https://en.wikiquote.org/wiki/Rasmus_Lerdorf
|
| Do you really want any of those people who were corrupted
| by PHP messing around with your code, if you relied on it
| being one way, and they assume it works the other way?
|
| It's not that you can't tell what it actually does, it's
| that you can't tell what the person who wrote it actually
| meant, which is more important than what it actually
| does, especially when it has bugs.
|
| Don't do many operations on one line, AND do use
| parenthesis, AND do use indentation, with no exceptions
| except for very simple expressions. Take every
| opportunity to use line breaks and vertical alignment to
| make symmetry and repetition and nesting visually
| obvious, like: float distance =
| sqrt( (x * x) + (y * y))
|
| Redundant parens, plus breaking expressions into multiple
| lines and indenting according to depth, unambiguously
| express programmer INTENT, so the reader doesn't need to
| wonder if the person who wrote it had a clue or was just
| showboating.
|
| Just use parenthesis, and put a comment on it, sailor.
|
| https://wellcomecollection.org/works/m33njwx3/items
|
| My copy of The Little Schemer won't open to page 13
| because of the jelly stains.
|
| https://vpb.smallyu.net/[Type]%20books/The%20Little%20Sch
| eme...
| dahfizz wrote:
| What is with the gay sailor condom ad? You're being
| completely ridiculous.
|
| I'm glad you enjoy Forth so much, I guess. I'm sure
| postfix will catch on any day now.
| sli wrote:
| According to its listing on the No Starch website[0], the
| PDF is (currently) 400 pages. I'm not a fan of that
| particular Haskell book but it's in no way even close to
| 881 pages.
|
| [0]: https://nostarch.com/lyah.htm
| Kalq wrote:
| Why don't you like that book and which Haskell book would
| you recommend then?
| bbarnett wrote:
| That's 800 pages double sided! Simply because the back
| side is blank, is no reason to nitpick.
| [deleted]
| tremon wrote:
| I don't get it. Wouldn't 800 pages double-sided require a
| PDF containing 1600 pages?
| bbarnett wrote:
| Sorry, been looking at new cars, and salespeople have
| been explaining new car, extended warranties to me.
| stonemetal12 wrote:
| 400 single sided printed pages. If you are trying to
| inflate the page count that is 800 pages, but every other
| page is blank.
| wiseowise wrote:
| Comparing C to Haskell is like comparing razor to laser
| scalpel.
| bryanrasmussen wrote:
| And not just any razor, a really useful one!
| pjmlp wrote:
| One of those that always cuts the user no matter how
| carefully they try to get hold of it.
| benj111 wrote:
| No it's a tool.
|
| I suppose you could compare it to a table saw. C is one
| without a guard or any other safety measures, so you need
| to be careful not to cut your fingers off. More modern
| languages have the guard and break etc.
|
| For general use you probably do want all the safety bits,
| but occasionally it is useful to be able to take it off
| to do a weird cut on a weird bit of wood.
|
| None of that necessarily means you _will_ cut your
| fingers off though.
| [deleted]
| pjmlp wrote:
| Which is why most workloads bring POSIX for the ride as means
| to make anything actually usefull.
| dahfizz wrote:
| POSIX is an OS API. You're complaining that C interacts
| with the operating system to do useful work? What language
| do you use that can do useful work without interacting with
| the OS?
| pjmlp wrote:
| POSIX is the part of the C standard library in UNIX, that
| should have been part of ISO C as well.
|
| It wasn't, so any C application that is more than a toy
| hello world with stdio, pings back into POSIX for any
| kind of meaningful work, that wants to stay cross
| platform.
|
| Basically it the the C runtime library, that wasn't part
| of ISO.
|
| I use JVM, .NET, Web and C++, not caring if the runtimes
| are bare metal or running on top of an OS, type 1
| hypervisor, or whatever.
| salawat wrote:
| >I use JVM, .NET, Web and C++, not caring if the runtimes
| are bare metal or running on top of an OS, type 1
| hypervisor, or whatever.
|
| If you're downloading a JVM binary, you're missing out on
| the build step. It's C dependent, friend. How do you
| think that VM interfaces with the OS? Go on. Try it. ldd
| the java executable.
|
| It's libc all the way down. C itself is a sort of "VM"
| specification utilized to create the tools to run the
| tools to build the tools that make other high level
| languages possible.
|
| Unless you create something entirely custom in platform
| specific assembly, you're running on C at some level.
| dahfizz wrote:
| I don't think you really understand what POSIX is.
|
| POSIX is an IEEE standard (example [1]). POSIX defines
| the Operating System API. You can see the C
| implementation of this API here[2].
|
| > so any C application that is more than a toy hello
| world with stdio, pings back into POSIX for any kind of
| meaningful work
|
| Simply calling printf relies on writing to a file
| descriptor. A "Hello world" application on linux uses
| posix. _ANY_ hello world application uses posix. Even
| your Java Hello world App will call into the posix APIs.
| `System.out.println` isn 't magic. It calls into the C
| posix implementation.
|
| If you want to do _anything_ in _any language_ (write to
| files, create threads, allocate memory, network
| communication), you need to go through the OS. POSIX is
| what defines that OS interface.
|
| > I use JVM, .NET, Web and C++, not caring if the
| runtimes are bare metal or running on top of an OS, type
| 1 hypervisor, or whatever.
|
| So you use POSIX, you just don't think about it.
|
| [1] https://standards.ieee.org/ieee/1003.1/7700/
|
| [2] https://en.wikipedia.org/wiki/C_POSIX_library
| metafunctor wrote:
| My Second Edition K&R (purchased in the mid-90s) is only 272
| pages, including the index.
| Taniwha wrote:
| This is because IBM 029 card punches don't support these
| characters right?
| wglb wrote:
| Or an ASR33
| dragonwriter wrote:
| I think the ISO/IEC 646 invariant character set is more the
| issue.
| aidenn0 wrote:
| I thought it was because of international character sets that
| lacked the punctuation of EBCDIC CP37 or ASCII.
|
| [edit]
|
| For example ISO/IEC 646 is ascii with punctuation replaced by
| other characters.
| Taniwha wrote:
| EBCDIC is very much IBM - on our old Burroughs machine we
| used to have to use cent signs (and something else that I
| forget) for square brackets and a 3-hole multipunch for ';'
| sargstuff wrote:
| stills leaves the issue of how to print out something that
| doesn't exist as a physical old style physical type face
| character. (way pre-dot matrix / laster printer stuff). --
| aka substituting 3 characters way more informative than
| blank space.
| aidenn0 wrote:
| My (possibly wrong) understanding is that trigraphs were
| a late addition to the ANSI standard, which would place
| it in late 80s, well into the CRT terminal and dot-matrix
| era.
| dijonman2 wrote:
| Fantastic book. I used Learn C in 21 days and that is what
| started everything for me. I had a second book on Linux
| administration and installed Slackware from 1.44mb disks,
| ultimately setting up pppd and using Mosaic.
|
| Great memories!
| kjs3 wrote:
| I, too, learned C by reading K&R cover to cover and solving all
| the exercises (in front of a Sun 3/160 running SunOS 3.5-ish).
| Even then back in those ancient days, it was obvious trigraphs
| were evil and should have been abolished to a special place in
| hell.
| [deleted]
| unwind wrote:
| I learnt it a few years before that, and I remember how reading
| K&R once I got it felt like having someone turn UP the lights,
| open the blinds, wash the windows and basically TURN UP THE SUN
| compared to things I read before. So much clarity.
|
| Number of times I've seen trigraphs in "real code": still zero.
| I hope it's the same for you.
| moomin wrote:
| I read it at a similar time, and I remember that feeling
| well. However, if you revisit it with a critical eye, you
| find a hundred places where a result isn't checked, bounds
| aren't checked, memory is leaked and so on.
|
| All of this was pretty much fine in the context in which it
| was written, but these days bullet-proofing things is pretty
| much mandatory and K&R's elegance disappears in the face of
| such challenges.
| [deleted]
| DonHopkins wrote:
| Years 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 wrote:
| That'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.
| benj111 wrote:
| Oh 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)
| DonHopkins wrote:
| Are you telling me that C compilers in the early 90's had
| bugs and confusing error messages??!!?!??? WTF?!??!?!?
| dhosek wrote:
| 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).
| watersb wrote:
| Great 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-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.
| sargstuff wrote:
| from [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 [2]
| https://www.emacswiki.org/emacs/CppTemplate
| planede wrote:
| Good news, in C++20 you can add <> there somewhere, although
| probably it can't be empty.
|
| Anyway, probably obscure enough: int main() {
| []<class=void>(){}(); }
| pjmlp wrote:
| And in C++23 drop the arguments parenthesis, so this is also
| valid lambda call, :) int main() {
| []{}(); }
| planede wrote:
| []{}() was always valid, but you can drop the arguments in
| more cases in C++23.
| jawadch93 wrote:
| cesaref wrote:
| This 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
|
| 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.
| Waterluvian wrote:
| 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?
| quickthrower2 wrote:
| I imagine microseconds or less
| sargstuff wrote:
| 0 if sed used to expand the trigraphs before passing output
| to cpp/compiler.
| quickthrower2 wrote:
| Always zero if you make it someone else's problem :-)
| NavinF wrote:
| microseconds, not milliseconds
| zik wrote:
| Probably not by any measurable amount
| pantalaimon wrote:
| They are already deprecated and removed in C23
| chromatin wrote:
| Wow, 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
| richbell wrote:
| I think C also has the elusive "down to" operator.
|
| https://stackoverflow.com/a/1642035
| creativemonkeys wrote:
| "-->" 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.
| [deleted]
| Natsu wrote:
| Honestly, I thought this was about a programming language
| called C? rather than C.
| rdlw wrote:
| In the spirit of C++ and C#, there could be a C?'1':'0'
| ryandrake wrote:
| I 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.
| Someone wrote:
| No, that's the next-to-last question. If they know that, you
| ask about digraphs <: and :> are [ and ]
| <% and %> are { and } %: is #
|
| (since C99, and expanded a bit later than trigraphs)
|
| 'Unfortunately', none of the characters used here can be
| coded using trigraphs, so you can't use trigraphs to generate
| digraphs in source.
| thrwyoilarticle wrote:
| Gasp! You mean they've heard the volatile question before?
| sidewndr46 wrote:
| The register keyword is far more interesting.
| Thorrez wrote:
| How about the restrict keyword.
| WithinReason wrote:
| Wow, I know all these. I only recently discovered bit
| addressing in C though.
| mpalczewski wrote:
| Why would you do this? Some weird insecurity?
| sirmoveon wrote:
| Salary negotiating leverage? The worst they feel the more
| likely they accept to be lowballed
| ryandrake wrote:
| Haha 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.
| virtualritz wrote:
| > Has Microsoft Windows finally been open-sourced or where did
| this come from?
|
| This comment on the SO post made my day. :D
| NegativeLatency wrote:
| There'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 wrote:
| Of course when you are willing to use preprocessor, you can do
| things like Bournegol:
| http://oldhome.schmorp.de/marc/bournegol.html
| sargstuff wrote:
| or throw exceptional loops :
| https://www.chiark.greenend.org.uk/%7Esgtatham/mp/
| sargstuff wrote:
| https://github.com/Hirrolot/metalang99
| sargstuff wrote:
| Or give C C++ functionality : https://libcello.org/
| kenniskrag wrote:
| trigraphs are removed in c++ 17
|
| https://en.m.wikipedia.org/wiki/C%2B%2B17#Removed_features
| amelius wrote:
| I've never seen them used anywhere.
| shakna wrote:
| They 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.
| WalterBright wrote:
| They were meant to support EBCDIC.
| mfost wrote:
| They 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.
| Rebelgecko wrote:
| They're good for obfuscating source code but AFAICT that's
| about it on modern machines
| sargstuff wrote:
| Less 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://www.gnu.org/software/gawk/manual/gawk.html#Signatur
| e...
| pjmlp wrote:
| They are still around in C though.
| KerrAvon wrote:
| gone in C23
| sargstuff wrote:
| ... but if someone sed it back in .....
| pjmlp wrote:
| I see, thanks.
| david2ndaccount wrote:
| They are being removed in C23.
| pjmlp wrote:
| I see, thanks.
| piesquaredarr wrote:
| Huh, I never realized that C++ standards were _removing_ C
| features. Time to be more careful about using g++ for
| everything.
| Jorengarenar wrote:
| https://mcla.ug/blog/cpp-is-not-a-superset-of-c.html
| Denvercoder9 wrote:
| C++ has never been a strict superset of C. The most obvious
| example is the "class" and "new" keywords which can be used
| as an identifier in C, but not in C++. There's more subtle
| differences as well, such as character literals having type
| int in C and char in C++.
| wheels wrote:
| Another really common one is that casting from _void *_ to
| any other type doesn 't require a cast in C, but it does in
| C++: #include <stdlib.h> int
| main() { int *foo = malloc(sizeof(int));
| return 0; }
|
| That works in C, but not in C++.
|
| There's actually another subtle different in there that
| _main()_ means "unspecified arguments" in C, and "no
| arguments" in C++. ("No arguments" in C would be
| _main(void)_.) However, it 's no longer commonly used that
| way in C, but casts from _void *_ to other types is very
| common in C.
| favorited wrote:
| The `func()` vs `func(void)` difference has been
| deprecated for a while, and is removed in C23.
| bee_rider wrote:
| Ah, what an elegant example, haha.
| tialaramex wrote:
| Using unions for type punning is legal C, but the exact
| same code has UB in C++
|
| The modern C++ way to do this ~safely isn't legal C, and
| yet the type pun isn't safe in C++. I believe using
| memcpy() to launder the bits is legal in both languages and
| in some cases your compiler can figure out what you're
| doing and not actually emit the unnecessary copy.
| sumtechguy wrote:
| I used a few different compilers for C in one project.
| Ended up at memcpy and byteswaping to get data between
| different instances of the code correctly (some ARM,
| mips, and x86, and each of those can set the byte order).
| Using a union is possible if it supports packing and the
| bytes happen to be in the same order and the compiler
| keeps the struct in the same order. I found that is not
| true of all compilers, by default. Massively annoyed
| having to rewrite about 50 file writes/reads that were
| nice and simple with massive memcpy cascades. Inside the
| same code on the same compiler you can get away with a
| lot of things. But port to another arch or try to get bin
| data out of your program into another (good luck). These
| days there are realistically 4 compilers people use and
| they tend to behave mostly the same, also nice libs that
| do most of this for you. That was the same project I
| learned not all printf's are created equal. Different
| CRTs do very different things even in the same compiler
| family. There is a reason everyone decided to use json
| and xml to transport data. Because of that mess.
| turminal wrote:
| Using g++ for C code is a recipe to get badly burnt - for
| unrelated reasons. Trigraphs are disabled in gcc by default
| anyway.
| professoretc wrote:
| That's true for any C++ compiler, really. Although C++
| tries to retain some element of compatibility with C, there
| have always been differences (you can name a variable
| `class` in C but not in C++).
| sltkr wrote:
| By default, GCC ignores trigraphs in C code too.
|
| You have to explicitly pass -std=c17 (or whatever) to get
| standard-conforming behavior including trigraphs.
| curling_grad wrote:
| Anecdote: 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
___________________________________________________________________
(page generated 2022-10-06 23:02 UTC)