karl@haddock.ISC.COM (Karl Heuer) (07/28/88)
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@haddock.isc.com), The Walking Lint