Path: utzoo!utgpu!water!watmath!clyde!rutgers!sri-unix!quintus!ok From: ok@quintus.UUCP (Richard A. O'Keefe) Newsgroups: comp.lang.c Subject: Re: Power operator? Summary: basic operations & procedure calls Message-ID: <520@cresswell.quintus.UUCP> Date: 11 Jan 88 03:47:36 GMT References: <11169@brl-adm.ARPA> <1559@rtech.UUCP> Organization: Quintus Computer Systems, Mountain View, CA Lines: 68 In article <1559@rtech.UUCP>, wong@llama.rtech.UUCP (J. Wong) writes: > One of the original motivations of the people who designed C was > that no operation should result in a function call being generated > in order to implement the language. On the PDP-11, not only did 32-bit integer *, /, and % generate subroutine calls, but C function entry and exit involved subroutine calls. These operations *could* have been performed by in-line code, but the space overhead would have been rather high. On quite a few machines the shift operators involve a function call when the shift count is not a constant. I hate to disillusion people (:-) but the plain fact is that the set of operators in C is (almost) identical to the set of operators in BCPL. There is one important exception: in BCPL the operators ~, &, and | are like !, &&, and || in "truth-value" context (argument of 'if', 'while', &c) or like ~, &, and | in "bit" context (assignment, argument passing). Here is a table in order of precedence: Construct BCPL C Constant 10, #47, #xFE 10, 047, 0xFE (examples) "string*N" 'c' "string\n" 'c' (expr) (expr) Cast {no types, not present} (type)expr Call expr(arg,...,arg) expr(arg,...,arg) Field field :: expr expr.field subscript array!wordoffset array[subscript] array%byteoffset {also array[subscript]} Address of @lvalue &lvalue Indirect !rvalue *rvalue Arithmetic e1 * e2 e1 * e2 e1 / e2 e1 / e2 e1 rem e2 e1 % e2 e1 + e2 e1 + e2 + e1 {omitted} e1 - e2 e1 - e2 - e1 - e1 Relational = ~= < <= > >= == != < <= > >= Shift << >> << >> Logical ~ ~ (bit context) {also ~} ! (truth-value context) & & and && | | and || e1 eqv e2 {use e1 ^~ e2} e1 neqv e2 e1 ^ e2 {^^ omitted} Conditional e1 -> e2, e3 e1 ? e2 : e3 Assignment e1 := e2 e1 = e2 Sequence e1 <> e2 e1, e2 The floating-point operations are (in the versions of BCPL that have them): #* #/ #+ #- #= #~= #<= #>= #< #> (no power operator!). Since everything is a "word", one has 36-bit integers and 36-bit floats, or 32-bit integers and 32-bit floats, or whatever. It is only at the statement and declaration level that C departs significantly from BCPL. In particular, C's switch() statement is almost identical to BCPL's SWITCHON(), except for one change that has never made sense to me. In BCPL, cases are terminated by ENDCASE, not by BREAK. So if you have a SWITCHON inside a loop, you can BREAK out of the loop without needing a goto. Confusing ENDCASE and BREAK has never made sense to me. Is there some deep reason for the choice of what is an operator and what isn't in BCPL? Almost certainly not, as it is a simplification of CPL which made so few concessions to hardware that I don't think it was ever fully implemented. I think the moral of it all is, go to the primary sources!