Preprocessor log()?

Discussion in 'C Programming' started by Richard Cavell, Feb 27, 2005.

  1. 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*.
     
    Richard Cavell, Feb 27, 2005
    #1
    1. Advertising

  2. Richard Cavell

    Chris Torek Guest

    In article <cvrcg3$o4b$>
    Richard Cavell <> wrote:
    >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.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Feb 27, 2005
    #2
    1. Advertising

  3. Richard Cavell

    Kevin Bracey Guest

    In message <cvrcg3$o4b$>
    Richard Cavell <> wrote:

    > 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.

    --
    Kevin Bracey, Principal Software Engineer
    Tematic Ltd Tel: +44 (0) 1223 503464
    182-190 Newmarket Road Fax: +44 (0) 1728 727430
    Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
     
    Kevin Bracey, Feb 28, 2005
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Henrik_the_boss
    Replies:
    0
    Views:
    2,698
    Henrik_the_boss
    Nov 5, 2003
  2. Amratash
    Replies:
    0
    Views:
    553
    Amratash
    Apr 13, 2004
  3. =?Utf-8?B?VG9tIFdpbmdlcnQ=?=

    My.Log.Writeexception not writing to Application Event Log.

    =?Utf-8?B?VG9tIFdpbmdlcnQ=?=, Jan 20, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    2,402
    =?Utf-8?B?VG9tIFdpbmdlcnQ=?=
    Jan 20, 2006
  4. Cronus
    Replies:
    1
    Views:
    708
    Paul Mensonides
    Jul 15, 2004
  5. unomystEz
    Replies:
    0
    Views:
    578
    unomystEz
    Nov 19, 2006
Loading...

Share This Page