108

It seems that the use of the exclamation mark ! to denote negation started with the C programming language (as far as I can tell from my Google research). Nowhere though is mentioned who and why chose this symbol specifically, other than that it was simply available.

So, the question is: when, by whom, and why was ! chosen?

19
  • 14
    Well, this usage was not inherited from BCPL, which used ! as the array indexing operator. (The Development of the C Language)
    – dan04
    Jun 14, 2021 at 18:16
  • 9
    Doesn't look like it's from APL, my "goto" language when it comes to wacky characters :! is the factorial function.
    – ErikF
    Jun 14, 2021 at 19:01
  • 32
    Probably because != is as close to ≠ as you can render in a limited character set, but it is only an opinion, not an answer. Jun 14, 2021 at 20:46
  • 18
    @BrianTompsett-汤莱恩: /= or |= would also work as approximations of , but C uses those operators for other things.
    – dan04
    Jun 14, 2021 at 21:56
  • 18
    The shame here is that UK keyboards have a key dedicated to the formal symbol for Logical Negation ¬ (and the broken-pipe symbol) - but the US keyboard doesn't - so methinks if K&R had a British keyboard for some reason then we'd be using better symbology all around, especially in C-derived languages today :)
    – Dai
    Jun 15, 2021 at 4:49

7 Answers 7

109

Since the few document trails on this topic quickly run cold, I contacted Ken Thompson. He confirmed that if there was anything he would have been influenced by at the time, it would have been BCPL and SMALGOL. But given that these don't use ! for negation, he "might have made it up".

I don't suspect there is anything more to it that can be researched.

3
  • 32
    If I may ask, how does one contact Ken Thompson? Jun 16, 2021 at 13:27
  • 13
    If Kaz is a Googler then it should have been pretty easy; when I last checked both Thompson and Kernighan were on the payroll, so they'll have appropriate internal corporate email addresses.
    – Tommy
    Jun 16, 2021 at 18:44
  • 8
    @Tommy: he isn't. When going from his profile, you quickly end up at the LinkedIn, CV etc. with his current employer. Ken's email address can easily be found with a quick duckduckgo search.
    – AnoE
    Jun 17, 2021 at 10:57
57

The ! was around as part of the B programming language, according to the "User's Reference For B" (K Thompson, Jan 1972).

Somewhere between BCPL and B, the decision was made to use !.

In the Reference above, I can't find an indication of why it was chosen. "The NOT prefix unary operator ! takes an integer value operand. The result is zero if the operand is non-zero. The result is one if the operand is zero."

13
  • 13
    @Someone_who_likes_SE: it's logical negation, so ! belongs to the same group as || and && logical operators, which evaluate numeric operands according to != 0 being true. C's other negation operators are arithmetic - (value negation, subtract-from-0), and ~ (bitwise inverse, one's complement negation). Fun fact: on a 1's complement machine, unary - and ~ are the same thing, I think. Jun 15, 2021 at 9:12
  • 2
    @ilkkachu: I was wondering whether there might be any difference in their semantics in C, not just the binary operation. e.g. whether -0 would create a 0xffffffffU bit-pattern like ~0 would (which may be a trap representation on some 1's complement machines, so you'd want to implement signed int -x in a way that did 1's complement subtraction from 0, not just flipped the bits, on such a machine). I also wondered about signed-overflow UB, but now that I think about it, only 2's complement has a number whose negation isn't representable in the same type. Jun 15, 2021 at 10:49
  • 3
    The PDP-1 was a ones complement machine, and yes negating a number gave the same answer as flipping all the bits. Except for zero. If you negate it, this gives all ones, which is minus zero. But the PDP-1 had some circuitry to convert minus zero to zero. I forget whether it activated in this case. Jun 15, 2021 at 11:28
  • 2
    Is it just a coincidence that ~ and ! are next to each other on the keyboard? Jun 15, 2021 at 11:38
  • 8
    @WalterMitty The various UNIX conventions are generally built around the keyboard layout of the ADM-3A terminal. (eg. ~ and HOME share a key, as do HJKL and the arrows keys.)
    – ssokolow
    Jun 16, 2021 at 1:31
31

Likely because it's wasn't a widely used mathematical operator, and wasn't a quote symbol.

Other answers have pointed out that ! was used in B and then found its way into C.

The popular "not equals" operators in computer languages are:

  • != → Probably meant to look like . ! means factorial, but it's not an arithmetic operator. Most popular languages don't have a factorial operator, and on most non-trivial factorial operations like combinations and permutations there are algorithms that let you not do the full factorial math to solve them.

  • <>< and > both have separate meanings in most languages, and < and > imply an order (i.e. something is greater than something else), which true and false don't really have.

  • =/= → The / already means divide, and /= means divide and save the results. It couldn't be used as a single character anyway, and a minor typo completely changes what it does.

  • '" (and back-ticks `) → The "not" symbol in math is usually the character written after the variable (so A'). It also indicates strings or characters, so it would have been confusing and likely difficult to parse. Back-ticks ` and ' look extremely similar so reading it would have been difficult. It's also pretty surprising how many programmers do not know what a back-tick is.

So out of all the ASCII symbols, ! is the one least likely to cause typos and confusion. It's on the wrong side of the variable to mean factorial, and even if someone was confused, a single run of the program would have shown them the error.

Some other choices and why they probably weren't in the running:

  • | - Already used to mean OR. Also, the pipe command, which was already used in Unix/Linux as a way to chain commands together, so probably not a good choice. People might have tried to chain functions together

  • % - Means modulo and percentage. Already widely used for something else.

  • : - Already used by labels and the ?: conditional shortcut. Looks really similar to ; which ended statements in C. Also was already used by Smalltalk and C++ for inheritance.

  • # - Part of preprocessor directives in C and used by many shells.

  • ^ - Sometimes means "to the power of" in languages, so already taken.

  • ? - Already a short-cut for if in many languages, and would imply you're asking a question instead of negation.

  • $ - Means money. Also heavily used by many shells to mean variable.

  • & - Means "and". Already used as a bitwise or logical AND in many languages.

  • ~ - Not widely used in most programming languages, but ~= means "approximately equal to" in mathematical text. So probably would have added more confusion.

  • @ - Means "at". Not widely used in programming languages, but widely used in emails, which were invented in 1978. Not a good choice because it's an abbreviation for a word.


The comments are awesome. At first trying to pull some into the answer, but too many, and too many great history points.

21
  • 19
    <> was used as not equal in several BASIC dialects.
    – UncleBod
    Jun 15, 2021 at 20:09
  • 7
    Neglected to mention it above; C does use : for the ternary operator (along with ?). Not sure when it dates from in C though (the ternary operator originated with CPL ca. 1963). Jun 15, 2021 at 21:43
  • 12
    Pipelines didn't enter Unix until 1973; B programming language was 1969. Jun 16, 2021 at 1:42
  • 6
    Regarding ' it is maybe worth noting that ! was originally ' overstruck with .
    – Adám
    Jun 16, 2021 at 7:57
  • 7
    Regarding ~: The C bitwise operators were assigned before the logical operators. ~ was assigned to bitwise negation, being somewhat similar to the mathematical ¬ symbol. Therefore, ~ was unavailable later when the logical operators were created.
    – DrSheldon
    Jun 16, 2021 at 16:34
19

When did ! as NOT surface?

BCPL defined a number of logical operators, but these were all bitwise logical operators:

4.5 Logical Operators

[paraphrased: bitwise logical]

      ~ E1 (also not E1)
or E1 & E2
or E1 \ E2

Some bitwise operators survived into B, particularly its AND (&) and OR (|) operators, whereas bitwise NOT did not. B introduced, however, the NOT unary prefix operator that was not a bitwise operator, but the integer logical NOT as we know it in C today:

4.2 Unary Operators

  1. The NOT prefix unary operator ! takes an integer rvalue operand. The result is zero if the operand is non-zero. The result is one if the operand is zero.

As this was a new operator not present in its predecessor BCPL, B had to make a decision as for what syntax to use for the operator. As this was moreover not to be confused with the bitwise NOT of BCPL, one might speculate that re-using ~ was not considered a good way forward. As for why ! was chosen given the (speculative) rejection of ~, another answer presents some good (albeit speculative) ideas.


What came first, != or !?

Finally, note that B also introduced the equality operators == (equal to) and != (not equal to), also not present in its predecessor, and it’s arguably

  • easier to see how != originated given it’s shape as compared to the non-ANSII symbol for non-equality, and
  • if so, how != as “not equal to” made breaking out ! as the logical “not” was a somewhat natural choice.
1
  • 2
    This is a well-written and sourced answer. Welcome to Retrocomputing!
    – DrSheldon
    Jun 17, 2021 at 19:00
8

I always assumed we stole OR and NOT from propositional logic. It's roughly 15 years older than programming languages, and writes things like p|q and p & !q. Sure, they prefer the small 2-line right-then-down for a "not", but you can't type that; likewise the almost-V and upside-down V for OR and AND.

9
  • 4
    In fact, the whole reason that backslash made it into ASCII in the first place was to allow programming languages to use \/ and /\ as operators.
    – dan04
    Jun 16, 2021 at 0:16
  • 6
    Could you add some source for the usage of ! that predates the programming usage?
    – blues
    Jun 16, 2021 at 6:51
  • 9
    Propositional logic is just 15 years older than programming languages???
    – Kaz
    Jun 16, 2021 at 7:51
  • 5
    “Big if true.” If “!” was was used in propositional logic before C, then this seems a very likely explanation. But the prefix symbols I can remember seeing for negation in earlier logic literature are ¬, –, and ~. This answer would be great if it could be expanded with a source citation. (And it’d be equally interesting to see a source for @dan04’s comment!) Jun 16, 2021 at 21:59
  • 3
    I recall we used to write propositions with . (or nothing) and +. AB+C is a lot shorter than A ∧ B ∨ C (though we knew that notation too) and the rules are the same as algebra. Negation (to the point of the current question) was an overbar in either notation. Jun 17, 2021 at 1:33
1

I don't know if this has the logical ring to it that many in the computing community appreciate, but I can't get past an emotional interpretation:

"DON'T do that!" always has a "!" on the end of it. At least, it certainly did since childhood for me. Other examples: "No!" and "I told you, NO!".

There's a pretty strong negation in that character. It symbolizes alarm, that there's something wrong. I'd choose that character for negation.

Even now, whenever I see an exclamation mark, there is a sudden amygdalic spasm and a subconscious urge to pull back my hands and cover my mouth while I stare I what I shouldn't have been doing.

So where in a positive case, it might be == "yes, this", its != "no, NOT this!". i.e. Stop. ALARM Stop what? Stop 'this'.

Before I encountered coding (which isn't very much, btw) or logic (perhaps even less), I used to use "!" in handwritten notes for lab protocols ("caution", "error", etc, (but also, "activated") or as a shorthand for pain/physical injury in my training diaries.

1

I recall in my pre-computer days throughout my college math major courses (1968-1970), we were using the ! symbol in proofs as negative (meaning not). It appears that the use of the symbol "!" as "NOT" was not first begun with the use of the programming language C (which was one of several programming languages I later used), but was likely brought into C because of its use in logic and mathematic proofs. If we are looking for why it was used in C, that appears to provide a rationale. My school notes and textbooks are long gone, but there are some online links that support my memory: (1) https://stat.ethz.ch/R-manual/R-devel/library/base/html/Logic.html (2) https://en.m.wikipedia.org/wiki/List_of_logic_symbols

3
  • Maybe so, but this doesn't answer the question of why.
    – Chenmunka
    Jul 2, 2021 at 9:02
  • If you have a reference to a textbook or any other material that was used in those courses that has the usage of !, and also predates the programming usage this could be a great answer.
    – blues
    Jul 2, 2021 at 9:05
  • 2
    You missed the most important part: ‘and also predates the programming usage’. Neither Wikipedia nor the R manual meet this criterion. Jul 4, 2021 at 9:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .