Preprocessor log()?

R

Richard Cavell

Hi,

I want to do something like this:

const int a = "283529";
const int b = log to base 2 of a;

and have it *at compile time*.
 
C

Chris Torek

I want to do something like this:

const int a = "283529";
const int b = log to base 2 of a;

and have it *at compile time*.

You cannot even do this:

% cat foo.c
const int a = "283529";
% cc -ansi -pedantic -c foo.c
foo.c:1: warning: initialization makes integer from pointer without a cast
%

Presumably you did not really mean to include the quotes.

If we fix that, so that "a" is a read-only variable initialized to
283529, we still have several problems, the first being that "a"
is a variable. You cannot initialize a second static-storage-duration
variable based on another variable; you can only use constants to
initialize static-duration variables. Remember that, in C, const
means "do not define a constant". (There are other languages in
which const *does* mean "constant"; but if you mean to use one of
those languages, you are in the wrong newsgroup.)

We can repair this by initializing both variables (whether read-only
or not) from a true constant, using either "#define" or "enum". Note,
however, that 283529 is a large enough value that it might exceed
the range for "int", so we really should use "long", and a #define
-- enumeration constants have type int, and if INT_MAX is 32767, the
sequence:

enum { A = 283529 };

should draw a diagnostic. (If INT_MAX is 2147483647, as it is on so
many implementations today, no diagnostic is required.) So now we
have:

#define A 283529
const long a = A; /* or int, if you are sure INT_MAX >= 283529 */
const int b = SOME_MACRO(A);

and we need to find a way to define SOME_MACRO so as to obtain
log2(283529).

Now we have one final problem: log2(283529) is approximately
18.113136779327283. What integer value do you want to represent
this? Both 18 and 19 are "reasonable" but at most one of them
is correct (although perhaps neither is correct).

Depending on your answer to this last problem, there is an obvious
way to define SOME_MACRO:

#define SOME_MACRO(x) \
((x) > 65536 ? [one set of options] : [other set of options])

where the expansion of one of the sets-of-options is:

(x) > 256 ? [one set of options] : [another set of options]

and these options again expand to something like:

(x) > 16 ? [one set of options] : [another set of options]

and so on, ending with:

(x) > 1 ? 1 : 0

(with an optional test for x < 1 as well, although what value to
use here is again a puzzle).

(This version, with the tests for ">", is designed for rounding
up, so that b will be set to 19, based on A > 262144; if A is
between 131073 and 262144 inclusive, the result would be 18.)
 
K

Kevin Bracey

In message <[email protected]>
Richard Cavell said:
Hi,

I want to do something like this:

const int a = "283529";
const int b = log to base 2 of a;

and have it *at compile time*.

Chris Torek's answered this for your specific code. But here's my take.

The only straightforward way to do this sort of thing in the _general_ case
is to write a small program which is run at build time to generate the
required constants. For example:

#include <stdio.h>

int main(int argc, char **argv)
{
printf("const int a = %d\n", atoi(argv[1])));
printf("const int b = %d\n", (int) log2(atoi(argv[1]))); /* rounding? */
return 0;
}

then in your makefile

cc mkconstant
../mkconstant 283529 > constants.c

and #include "constants.c" where required.

Obviously this is extensible to large data tables etc. (Although in that case
computing at run-time may be better if memory is more important than start-up
time).

The only thing to be wary of (particularly for math.h functions) is that you
may get different answers at build-time and run-time if your host and target
platforms are different.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top