power operator as an extension
Karl Heuer
karl at haddock.ISC.COM
Thu Jul 28 08:55:47 AEST 1988
As expected, the X3J11 committee has decided not to add an exponentation
operator to ANSI C. Given the charter of the committee, this was an
appropriate decision: there is no prior art. Yet I (and others, including
many fortran converts) would find such an operator useful.
I suggest that individual implementors add this feature to their ANSI C
compilers as an experimental extension. If people need this operator, they'll
prefer to buy compilers that support it. If many compilers support it, it'll
have a chance at being blessed in the second standardization (1999?).
In particular, I wonder if this would be interesting to the maintainers of GNU
cc, which I believe already supports at least one fortranish extension. I'm
cross-posting this to gnu.gcc, but followups not related to GNU should
probably go to comp.std.c only.
I suggest "*^" for the symbol, as it doesn't conflict with existing syntax,
and is somewhat mnemonic. ("^^" would also fit the bill, but this looks as if
it should mean logical-xor.) The grammar should be revised thus:
power-expression:
cast-expression
cast-expression *^ power-expression
multiplicative-expression:
power-expression
multiplicative-expression * power-expression
multiplicative-expression / power-expression
multiplicative-expression % power-expression
(Also, "*^=" should be added to the list of assignment operators.)
In the expression x *^ y, x can be any integral or floating expression;
its type is the type of the result. The exponent y must be an integral
expression; if x has integral type, then y must be nonnegative. If y==0,
then the value is 1 (even if x==0 also).
Here are my prebuttals to some anticipated objections.
] We don't need to raise numbers to a power.
Some of us do. Having to use a temporary just to square an expression is a
real pain.
] Negative exponents should be allowed even if the base is an int.
I don't care whether 3*^-1 returns 0 or -1431655765 or dies with a core dump.
All three answers can be justified, so it's probably best to leave this as an
undefined situation, just like a negative shift. (Of course, if there is a
consensus on the "right" answer in 1999, it may get blessed anyway.)
] The precedence is wrong; -x*^2 should mean (-x)*^2, not -(x*^2).
The compiler (or lint) should produce a warning for that construct, then. The
alternatives are to put *^ between postfix unary and prefix unary (which would
screw up expressions like *p++ *^ 2), or to split off unary minus into its own
precedence level (I don't think it's worth it).
Besides, the proposed precedence agrees with that of bc.
] It should allow floating-point exponents, too.
Less necessary, since the pow() function already handles this, and is probably
just as efficient. But you could add it if you like. (Cf. extending "%" to
floating-point operands.)
] None of this is necessary, because pow() exists. In fact, pow() can be
] implemented as a builtin which optimizes integral exponents.
There is no guarantee that pow() will produce the right answer. On my
machine, (int)pow(2.0, 3.0) produces 7 instead of 8. Unless X3J11 is willing
to guarantee the accuracy of the result (even for those implementations that
choose not to inline it), this is not a solution.
] An operator for a non-simple function runs counter to the Spirit of C.
It has been reported that nearly all (95%?) uses of exponentiation in actual
programs used a small, constant, integral exponent. This *is* a simple
operation. The general case may require more work, but this is also true of
the shift operators on some architectures.
] 0*^0 is mathematically indeterminate; it should be undefined, not 1.
It has to be 1, e.g. for a polynomial: sum a[i]*x*^i. This is consistent
with mathematical usage; 0*^0 is only indeterminate when the exponent is a
continuous variable. (And even then, the result is "almost always" 1.)
Karl W. Z. Heuer (ima!haddock!karl or karl at haddock.isc.com), The Walking Lint
More information about the Comp.std.c
mailing list