Hacker News new | past | comments | ask | show | jobs | submit login
New C++ experimental feature: The tadpole operators (msdn.com)
129 points by ingve on May 25, 2015 | hide | past | favorite | 62 comments



This is a joke. For those who didn't get the joke:

1. ~ and - are separate operators. - negates, ~ does this: http://stackoverflow.com/a/7207406

2. Integers on computers are typically represented in two's complement notation: http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html

3. Now that we know how all the parts work, we can put them together step by step:

    ~-0010 => ~1110 => 0001
    -~0010 => -1101 => 0011


It's a side effect of two's complement representation of integers. There ought to be a repository somewhere for neat tricks like this (with a warning never to use them in production).

    FOR ENTERTAINMENT PURPOSES ONLY


There is, and I can't recommend it highly enough.

http://www.amazon.com/Hackers-Delight-2nd-Henry-Warren/dp/03...


Was going to recommend Hacker's Delight, and saw I was too late :)


One of the "tadpole" operators is actually on the cover right above "Delight".


I own this book, and it is fantastic.

There's also HAKMEM[1] and the FXT book[2].

[1]: http://www.inwap.com/pdp10/hbaker/hakmem/hakmem.html [2]: http://www.jjj.de/fxt/


For those saying that this is unreadable, I really think that the trigraph alternative is for you! Instead of ~- and -~, you can use ??-- and -??-. IMO, those are much clearer.


The joke has already been explained in the comments there, yet people are still posting comments there oblivious of it...


I really can't figure out why so many people read The Old New Thing, or perhaps more accurately, feel compelled to comment in the comment section. This post is perfectly typical of the level of technical comprehension necessary to enjoy the blog. You are routinely expected to (after explanation at least) be able to understand COM, or the details of the Windows message pump, or how C++'s deallocation interacts with Windows process shutdown, or how threading interacts with destructors, or as in this case, get the joke without having it explained for you, but the comment sections are always populated by dozens of people who are just lost as can be. I don't know how they get there in such quantity, or why they seem to collectively stay. (Do they get to the blog via google searches and stick around because they think it's a place to complain about Windows? It's certainly at least one popular pasttime....)

I'm grateful that Raymond Chen seems to have a lot of patience for it, because The Old New Thing is a unique gem and would be irreplaceable if shut down, so I'm glad he keeps at it. May his patience stay strong.


A decent number of his posts are fascinating historical stories that don't require deep technical knowledge to enjoy, so I assume those draw in readers that stick around despite not understanding most of what he posts.


Yeah, I go back to it a lot for this reason, despite having little of the necessary knowledge to enjoy the more technical posts - I would never comment, but I can understand fully why people [often näively] do


His replies to some of the comments wink at the possibility that he thoroughly enjoys the rancor and consternation stirred in the minds of that particular subset of his readers.

e.g.

  That problem will go away once the optimizer is 
  taught to recognize this operator. Then we could 
  call it the rocket-powered tadpole.
    - Raymond
Consider the people, who haven't commented, instead simply skimming this post, without reading deeper, then showing up to work on Monday, and dutifully explaining to colleagues about a new operator they learned of.


"I'm grateful that Raymond Chen seems to have a lot of patience for it, because The Old New Thing is a unique gem and would be irreplaceable if shut down, so I'm glad he keeps at it. May his patience stay strong."

A couple of years ago he was much more cynical about it, mentioning giving up all together IIRC. Maybe he had a spiritual epiphany about the nature of idiocy on the internet or something, nowadays he seems to enjoy stringing the clueless-and-unwilling-to-learn along a bit.

But yeah, the things he puts up with...


I have to admit i had to look up "two's complement" to get the explanation.


This is of course a joke. Here is why it holds in general. If x is signed number in two's complement representation then

    x + ~x = -1
because x has a 1 where ~x has a 0 and vice versa and because all ones 11...111 in two's complement always represents -1 [ * ].

Transformation of the last formula yields

    x + 1 = -~x
The other "tadpole" operator can be derived from the above one by setting x = -y

    -y + 1 = -~-y
    y - 1 = ~-y
[ * ] This follows from the fact that the sum of all powers of two from 0th to (n-1)th is equal to 2^n - 1. Now, if the sign of the most significant bit in all-ones binary number 11..111 is flipped then the sum becomes -1.


Are there any other named C++ pseudo-operators? For example, the "clown eyes" operator !! commonly is used to coerce a boolish value to a bool. :)


In Mac programming (pre-OSX) it was common for the OS to give you memory blocks not using a pointer, but using a 'handle', which under Mac OS<=9 meant "a pointer to a pointer" (where the direct pointer was under OS control so that it could move memory blocks around in low-memory situations. By comparison, a 'handle' in Windows is a "memory block the contents of which you don't know what they are". On Mac OS<=9, you did know the contents; you just had to double-dereference your pointer to reach them)

This meant that when accessing data through these handles, you had to write code like this:

    (*handle)->field;
or

    (**handle).field;
Eventually, someone coined a pseudo-operator for reaching fields from a handle without requiring parentheses:

    handle[0]->field;  
[0]-> was named the "sproing" operator (on the theory that it indicates the desired value popping out of a box).


> By comparison, a 'handle' in Windows is a "memory block the contents of which you don't know what they are".

This is incorrect.

In Windows, the HANDLE is a typedef for a void pointer, but its usage is usually 100% analogous to a file descriptor - i.e. it is a token passed to kernel space, where the kernel looks it up in a per-process table of open files. I say "usually" because some components have re-used the HANDLE typedef for things which are not kernel objects - for example the HANDLE that comes from FindFirstFile() is actually a pointer to a structure in user-space [which AFAIK itself has a HANDLE to the directory].


That's true for some handles in Win32, but (since we're talking about classic MacOS) Win16 handles were usually NEAR pointers inside kernel segments.


True! That was a disaster; only 64K (16 bits) handles were possible across all processes. Many APIs had to be deprecated and redesigned when it went 32-bit.

I've argued for using uuids for handles from here on out. They are endless; no effort to coordinate handle spaces is ever needed; they work locally and on the network; on some architectures they are even a register width scalar.


That should be "sprong" not "sproing". I restored Maf Vosburgh's page here: http://textmail.net/sprong/sprong.html


There is the down-to pseudo-operator --> as in

    int x = 3;
    while(x --> 0) {
      std::cout<<x<<"\n";
    }


In addition to the rightward arrow, there's the leftward arrow:

    int x = 3;
    while(n <-- x) {
        cout << x << endl;
    }
which is different because it doesn't include the lower bound `n`. And of course, if typing the ">" is too taxing, the "---" operator is equivalent to the "-->" operator:

    int x = 3;
    while(x --- n) {
        cout << x << endl;
    }
A few more goodies in this style at http://steike.com/code/useless/evil-c/ (home of the zip-quine.)


A crying face is called "ever"

    #define ever (;;)

    for ever {
        // do something
    }


"clown eyes"? That's the Bugs Bunny operator!


I don't know if it's named, but there's the !!?!!? operator [1]

    !ErrorHasOccured() ??!??! HandleError();
[1] http://stackoverflow.com/questions/7825055/what-does-the-c-o...


i'd call that the bunny operator because it reminds me of the sanrio bunnies.


    That problem will go away once the optimizer is taught to recognize this operator. Then we could call it the rocket-powered tadpole. -Raymond
It seems GCC (4.9.2) already recognizes the operator and generates optimal instructions.


Edit: It's a joke but also teaching you a trick. I like.


Strong force '~' finally makes it into C++.


The tadpole operator has been supported in JavaScript, Ruby, and Python for years.


Yet another case of C++ lagging behind superior languages.


Horror followed by lolling.


To the friendly people downvoting this - Horror at seeing microsoft would do something so crazy, laughing after realizing I had been tricked by two's complement.


Reminds me the "goes to" operator

    int x = 10;
    while (x --> 0) printf("%d\n", x);
prints 9 ... 0. The operator is pronounced as "as x goes to 0"


MS sure got a lot of serious hater... Why so serious?


The sperm operator (as it should be called) wont work if your vars are unsigned ints, floats or doubles.


Very good. Back to work now.


I wish they introduce "in" as an operator.


instead of down voting and running away, provide constructive feedback as to why you think this isn't a good idea.


Pfft, trust Microsoft to push nonportable code.


Au contraire, mon ami: this feature is supported on all major compilers. ;)


I'm pretty sure that C doesn't guarantee a two's-complement representation. Not so sure about C++. Either way, it makes for a cute novelty article, and a really terrible idea.

Raymond should've saved it for the next April Fools' Day.


It's supported by all major compilers, but some may have buggy implementations if you try to target a non-two's-complement architecture. Clearly they need to fix those bugs!


Right, the tilde operator is supported, but the math trick in question only works on a twos-complement machine. So it's non-portable in the sense that the language spec doesn't guarantee a particular behavior.


Yup. If it wasn't clear, my comment above was a joke :-P


You got it. Both C (C11 §6.2.6.2) and C++ (C11 §3.9.1) permit two's complement, one's complement, and signed magnitude representation of integers. With one's complement, “−” ≡ “~” so “−~” and “~−” both do nothing. With signed magnitude, “−~” and “~−” both give the same result, which is the difference between the value and the maximum integer of the same sign.


Is it unreasonable for me to want a C/++ standard that's just "What's mostly standard by all major compilers" so we can stop nitpicking about implementation details most people never encounter?


At the time the first version of the C standard was being prepared, the practice of writing C that would only work with the ‘major compiler[s]’ had the nickname “All the world's a VAX”. Now consider the last time you used a VAX.


The VAX is a little-endian, 8-bit bytes, 32-bit datapath, 2's complement machine.

Consider the last time you used a machine with big endian, non-8-bit-bytes, and something other than 2's complement integer representation...

At the time of the C standard, architectures were far more diverse; for better or worse, most of the more esoteric ones seem to have died off, leaving us with the ones that do happen to share many characteristics with a VAX.


I used a 6-bit variable wordlength decimal arithmetic machine on Saturday. (See my post on mining Bitcoin on the IBM 1401.) And someone is writing a C compiled for this machine...


Used a big endian machine ... um ... thursday. I've been on vacation/holiday since then.


Out of curiosity, are there any common architectures that are wildly different on those basises from x86/x64/ARM?


I can't think of any general-purpose architectures in common use which are really odd, but some DSPs have a 24-bit "byte". The microcontroller world is a bit more diverse too, especially with many of them being Harvard architectures (e.g. C compiles to 8051 with 24-bit big-endian pointers, and the various PICs have odd instruction-word sizes like 14 bits).

However, all of those still use 2's-complement integers. According to Wikipedia a few existing mainframes use 1's complement (CDC 3000/6000, UNIVAC 1100/2200).

I know the standard allows different bit representations, but practically speaking, today you're almost never going to find anything other than 2's complement integers and IEEE floating-point; and if you do happen to be working on one of those rare and unusual machines that don't, I think it'd be the least of your worries... even Linus says he doesn't care about Linux running on non-two's-complement or odd byte-size machines.


Arm and powerpc are bi-endian...


this is effectively bitwise math, so it's actually supported in any language offering the minus and binary complement prefix operators.

Drop this into your address bar: javascript:var%20x=100;alert("x="+x+"\nx-1="+(~-x)+"\nx+1="+(-~x));


What demented mind invented this? It's not posted on April 1st so I'm not sure it's meant as a joke. Also it's on msdn.com.

Tilde and minus look just alike and make reading the code much harder if used together. "Look there's a --i oh no, it's actually -~i or is it ~-i or ~~i?"


It's just regular unreadable code. ~ and - are both prefix operators: bitwise complement and negation, respectively. With two's-complement arithmetic, "complement then negate" adds one while "negate then complement" subtracts one.


I got that feeling again when I was trying to learn 6502 assembly.

Amusingly at least in gcc

#\\ this appears legal


Raymond Chen rants about other developers doing stupid things - his job is basically to help them get stuff done in 'the right way' from what I can tell, so he finds a lot of weirdness like this.

My impression is that this is a parody of something ridiculous he found.


Sometimes I can't tell if people are being serious about their objections to this or if they are willingly oblivious.


Indeed. It's more interesting that an explanation (top comment) was posted one hour before this objection to the "feature."




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: