Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!security!genrad!decvax!yale-com!leichter From: leichter@yale-com.UUCP (Jerry Leichter) Newsgroups: net.lang.c Subject: Re: compile-time function - (nf) Message-ID: <2177@yale-com.UUCP> Date: Sat, 15-Oct-83 10:11:27 EDT Article-I.D.: yale-com.2177 Posted: Sat Oct 15 10:11:27 1983 Date-Received: Tue, 18-Oct-83 00:03:34 EDT References: hp-pcd.2079 Lines: 51 You can get your particular example to work by doing: #define LOG2(n) ((...(n == 2) ? 1 ) : (n == 4) ? 2 : ... (You can probably do without all the parens, but I can never remember for sure how precedence and associativity works for ?: so I play it safe...) The above will give you the code you want as a side-effect of constant folding, which is present in every C compiler worth looking at. It's an interesting fact that many compilers do constant folding over expres- sions, but hardly any - in fact, I don't know of any at all - do it across statements - although taking constants out of loops is, in a sense, doing exactly that. I don't think any C compiler will "fold" if (2=1) a = 0 else if (2 == 2) a = 1 etc. This is unlikely to come up, except in code generated by some other program (or a macro - but C macros aren't really very handy for constructing more than single statements anyway) - but this isn't common, so the compilers aren't designed to deal with it. So: In answer to your general question: If you can express your compile- time function as a single expression, constant-folding should get you the effect you desire. The presense of the ?: operator means you can put in conditionals. You can also put in calls to other macros. Unfortunately, you CANNOT use recursion: #define fact(n) (n == 1) ? 1 : n * fact(n - 1) will put every C compiler I've ever seen in a loop: Unfortunately, the compile-time evaluators do NOT respect the "non-monotonicity" (to use the term from formal semantics) of :?, &&, and ||. They always evaluate ALL arguments, and then discard the one they don't need. I.e. a = (X == 0) : 0 ? (1 / X) (where X is a pre-processor constant) SHOULD work; it would work if X were a variable; but it will cause most C compilers to die a horrible death when X happens to be 0. If :? was handled correctly, #define could be used recursively and the resulting compile-time language would be universal. (At least in principle. Most C compilers also have some hard limits on expression complexity, and will blow up if you really try this for more than "toy" cases.) -- Jerry decvax!yale-comix!leichter leichter@yale