using pre-processor to count bits in integer types...

Discussion in 'C Programming' started by Chris M. Thomasson, Jan 15, 2009.

  1. How "reliable" is the following code:
    ____________________________________________________________
    #include <stdio.h>
    #include <limits.h>


    #define COUNT_BITS_X_CALC(mp_value, mp_level) \
    (! ((mp_value) >> (CHAR_BIT * (mp_level)))) \
    ? (CHAR_BIT * (mp_level))


    #define COUNT_BITS_X(mp_value) ( \
    (COUNT_BITS_X_CALC(mp_value, 1) \
    : (COUNT_BITS_X_CALC(mp_value, 2) \
    : (COUNT_BITS_X_CALC(mp_value, 4) \
    : (COUNT_BITS_X_CALC(mp_value, 5) \
    : (COUNT_BITS_X_CALC(mp_value, 6) \
    : (COUNT_BITS_X_CALC(mp_value, 7) \
    : (COUNT_BITS_X_CALC(mp_value, 8) \
    : (COUNT_BITS_X_CALC(mp_value, 9) \
    : (COUNT_BITS_X_CALC(mp_value, 10) \
    : 0))))))))) \
    )


    #define COUNT_BITS(mp_value) COUNT_BITS_X(mp_value)


    #if (COUNT_BITS(USHRT_MAX) == 16)
    typedef short int int16_type;
    typedef unsigned short int uint16_type;
    #else
    # error Platform does not provide an exact 16-bit integer! ;^(...
    #endif


    int main(void) {
    printf(
    "char is %lu bits\n"
    "short is %lu bits\n"
    "int is %lu bits\n"
    "long is %lu bits\n"
    "int16_type is %lu bits\n",
    (unsigned long int)COUNT_BITS(UCHAR_MAX),
    (unsigned long int)COUNT_BITS(USHRT_MAX),
    (unsigned long int)COUNT_BITS(UINT_MAX),
    (unsigned long int)COUNT_BITS(ULONG_MAX),
    (unsigned long int)(CHAR_BIT * sizeof(int16_type))
    );

    return 0;
    }
    ____________________________________________________________




    I am tinkering around with different ways to use the pre-processor to
    determine exact number of bits in integral types. Is there a much better way
    to do this? What am I missing here?




    Thanks.
    Chris M. Thomasson, Jan 15, 2009
    #1
    1. Advertising

  2. On 15 Jan, 22:40, "Chris M. Thomasson" <> wrote:
    > How "reliable" is the following code:
    > ____________________________________________________________
    > #include <stdio.h>
    > #include <limits.h>
    >
    > #define COUNT_BITS_X_CALC(mp_value, mp_level) \
    > (! ((mp_value) >> (CHAR_BIT * (mp_level)))) \
    > ? (CHAR_BIT * (mp_level))
    >
    > #define COUNT_BITS_X(mp_value) ( \
    > (COUNT_BITS_X_CALC(mp_value, 1) \
    > : (COUNT_BITS_X_CALC(mp_value, 2) \
    > : (COUNT_BITS_X_CALC(mp_value, 4) \
    > : (COUNT_BITS_X_CALC(mp_value, 5) \
    > : (COUNT_BITS_X_CALC(mp_value, 6) \
    > : (COUNT_BITS_X_CALC(mp_value, 7) \
    > : (COUNT_BITS_X_CALC(mp_value, 8) \
    > : (COUNT_BITS_X_CALC(mp_value, 9) \
    > : (COUNT_BITS_X_CALC(mp_value, 10) \
    > : 0))))))))) \
    > )
    >
    > #define COUNT_BITS(mp_value) COUNT_BITS_X(mp_value)
    >
    > #if (COUNT_BITS(USHRT_MAX) == 16)
    > typedef short int int16_type;
    > typedef unsigned short int uint16_type;
    > #else
    > # error Platform does not provide an exact 16-bit integer! ;^(...
    > #endif
    >
    > int main(void) {
    > printf(
    > "char is %lu bits\n"
    > "short is %lu bits\n"
    > "int is %lu bits\n"
    > "long is %lu bits\n"
    > "int16_type is %lu bits\n",
    > (unsigned long int)COUNT_BITS(UCHAR_MAX),
    > (unsigned long int)COUNT_BITS(USHRT_MAX),
    > (unsigned long int)COUNT_BITS(UINT_MAX),
    > (unsigned long int)COUNT_BITS(ULONG_MAX),
    > (unsigned long int)(CHAR_BIT * sizeof(int16_type))
    > );
    >
    > return 0;}
    >
    > ____________________________________________________________
    >
    > I am tinkering around with different ways to use the pre-processor to
    > determine exact number of bits in integral types. Is there a much better way
    > to do this? What am I missing here?


    You are missing number 3 from your list of possibilities! The
    same thing could be written much more clearly by checking
    whether the value you are testing is equal to 2^n - 1 for
    successive values of n. You would need to write a larger list
    but it would look clearer. For example

    #define COUNT_BITS(n) ( \
    (n) == 255 ? 8 : \
    (n) == 511 ? 9 : \
    (n) == 1023 ? 10 : \
    .....
    )

    A bit more complicated but still (IMO) clearer is

    #define COUNT_BITS(n) ( \
    (n) == ( (1 << CHAR_BIT) -1) ? CHAR_BIT : \
    (n) == ( (1 << 2*CHAR_BIT) -1) ? 2*CHAR_BIT : \
    (n) == ( (1 << 3*CHAR_BIT) -1) ? 3*CHAR_BIT : \
    .....
    )

    (Neither one tested)

    I have a vague recollection that a while ago someone posted a
    macro which did what you wanted (or something close) and could
    handle ridiculously large numbers of bits. Sadly I haven't
    stored the link and some Google search didn't find the thread
    I was looking for. I would love to see that again.

    But it would be even simpler if you didn't use the preprocessor
    but did it during runtime in the beginning of your programme. Is
    there any practical reason you want to use the preprocessor ?
    Spiros Bousbouras, Jan 15, 2009
    #2
    1. Advertising

  3. "Eric Sosman" <> wrote in message
    news:1232061810.681510@news1nwk...
    > Chris M. Thomasson wrote:
    >> How "reliable" is the following code:
    >> [... see up-thread ...]

    >
    > "Reliable" in the face of what threats or eventualities?
    > It doesn't work in the presence of padding bits, it might not
    > work for UINTMAX_MAX or INTMAX_MAX, it definitely won't work for
    > floating-point types ... I'm not sure what realm of possibilities
    > you're concerned about.


    I would only ever pass the following values to the `COUNT_BITS' macro:


    UCHAR_MAX
    USHRT_MAX
    UINT_MAX
    ULONG_MAX


    I am assuming that the number of bits it takes to hold any of those values
    will be a multiple of `CHAR_BIT'.




    >> [...]
    >> I am tinkering around with different ways to use the pre-processor to
    >> determine exact number of bits in integral types. Is there a much better
    >> way to do this? What am I missing here?

    >
    > The total number of bits in a type is `sizeof(type) * CHAR_BIT'.
    > Excluding possible padding bits seems difficult. I guess you could
    > change your procedure to increase the shift distances by one bit at
    > at time instead of CHAR_BIT, and test for equality to one instead of
    > zero (to guard against a too-wide shift), but you've still got to
    > figure out how many tests to make: C99's integers go up to at least
    > 64 bits, and possibly beyond.


    I could shift by one. Humm, well I also could add support for a couple of
    hundred bits. This macro would be contained in a dedicated header file, so
    its not that bad.




    > The "much better way" -- well, can you formulate your questions
    > in terms of ranges rather than in terms of logarithms? That is, how
    > badly do you need actual bit counts?


    This macro would only get invoked when the end user build system for my
    library determines that its being compiled on an "unknown" platform.
    Something like:




    /* try to determine operating system */
    /* [...] */


    /* try to determine architecture */
    /* [...] */


    /* try to determine compiler */
    #if defined (COMPILER_VENDOR_1)
    # include "compiler/vendor/1/core.h"
    #elif defined (COMPILER_VENDOR_2)
    # include "compiler/vendor/2/core.h"
    #elif
    # include "compiler/vendor/unknown/core.h"
    #endif




    The `compiler/vendor/.../core.h' files are required to define some types
    that have exact number of bits. If I know the compiler, I will use specific
    extensions to get the job done. However, if the compiler is unknown, well, I
    need to at least "attempt" to render the correctly sized types. I need this
    to all be performed at compile time.
    Chris M. Thomasson, Jan 16, 2009
    #3
  4. On 16 Jan, 00:00, "Chris M. Thomasson" <> wrote:
    > This macro would only get invoked when the end user build system for my
    > library determines that its being compiled on an "unknown" platform.
    > Something like:
    >
    > /* try to determine operating system */
    > /* [...] */
    >
    > /* try to determine architecture */
    > /* [...] */
    >
    > /* try to determine compiler */
    > #if defined (COMPILER_VENDOR_1)
    > # include "compiler/vendor/1/core.h"
    > #elif defined (COMPILER_VENDOR_2)
    > # include "compiler/vendor/2/core.h"
    > #elif
    > # include "compiler/vendor/unknown/core.h"
    > #endif
    >
    > The `compiler/vendor/.../core.h' files are required to define some types
    > that have exact number of bits. If I know the compiler, I will use specific
    > extensions to get the job done. However, if the compiler is unknown, well, I
    > need to at least "attempt" to render the correctly sized types. I need this
    > to all be performed at compile time.


    You could run a programme which tests these things,
    writes a configuration file with preprocessor directives
    and then the compilation of your library begins. So
    basically a much simpler version of what autoconf does.
    Spiros Bousbouras, Jan 16, 2009
    #4
  5. Spiros Bousbouras <> wrote:
    > ...
    > A bit more complicated but still (IMO) clearer is
    >
    > #define COUNT_BITS(n) (                           \
    > (n) == ( (1 << CHAR_BIT) -1) ? CHAR_BIT :         \
    > (n) == ( (1 << 2*CHAR_BIT) -1) ? 2*CHAR_BIT  :    \
    > (n) == ( (1 << 3*CHAR_BIT) -1) ? 3*CHAR_BIT :     \


    There are a few problems with this:
    n may be a signed type
    n may be a padded type
    n may be wider than the left shifted 1 (int)
    [Even 1<<CHAR_BIT can potentially invoke UB.]

    <snip>
    > I have a vague recollection that a while ago someone
    > posted a macro which did what you wanted (or something
    > close) and could handle ridiculously large numbers of
    > bits.


    Hallvard B Furuseth once posted the following (which
    I've edited slightly due to line wrap issues)...

    /* Number of bits in inttype_MAX, or in any (1<<b)-1
    where 0 <= b < 3E+10 */
    #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    /0x3fffffffL %0x3fffffffL *30 + \
    (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    12/((m)%31+3))

    --
    Peter
    Peter Nilsson, Jan 16, 2009
    #5
  6. On 16 Jan, 00:28, Peter Nilsson <> wrote:
    > Spiros Bousbouras <> wrote:
    >
    > > I have a vague recollection that a while ago someone
    > > posted a macro which did what you wanted (or something
    > > close) and could handle ridiculously large numbers of
    > > bits.

    >
    > Hallvard B Furuseth once posted the following (which
    > I've edited slightly due to line wrap issues)...
    >
    > /* Number of bits in inttype_MAX, or in any (1<<b)-1
    > where 0 <= b < 3E+10 */
    > #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    > /0x3fffffffL %0x3fffffffL *30 + \
    > (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    > 12/((m)%31+3))


    Thank you. This had been bugging me for a while.
    Spiros Bousbouras, Jan 16, 2009
    #6
  7. "Eric Sosman" <> wrote in message
    news:1232061810.681510@news1nwk...
    > Chris M. Thomasson wrote:
    >> How "reliable" is the following code:
    >> [... see up-thread ...]

    >
    > "Reliable" in the face of what threats or eventualities?
    > It doesn't work in the presence of padding bits, it might not
    > work for UINTMAX_MAX or INTMAX_MAX, it definitely won't work for
    > floating-point types ... I'm not sure what realm of possibilities
    > you're concerned about.
    >
    >> [...]
    >> I am tinkering around with different ways to use the pre-processor to
    >> determine exact number of bits in integral types. Is there a much better
    >> way to do this? What am I missing here?

    >
    > The total number of bits in a type is `sizeof(type) * CHAR_BIT'.
    > Excluding possible padding bits seems difficult. I guess you could
    > change your procedure to increase the shift distances by one bit at
    > at time instead of CHAR_BIT, and test for equality to one instead of
    > zero (to guard against a too-wide shift), but you've still got to
    > figure out how many tests to make: C99's integers go up to at least
    > 64 bits, and possibly beyond.
    >
    > The "much better way" -- well, can you formulate your questions
    > in terms of ranges rather than in terms of logarithms? That is, how
    > badly do you need actual bit counts?


    Let post code with a shift by one:
    ______________________________________________________________________
    #include <limits.h>
    #include <stdio.h>


    #define CHECK_BIT_X(n, b) (((n) >> (b)) == 1) ? (b) + 1


    #define COUNT_BITS_CALC_X(n, b) ( \
    (CHECK_BIT_X(n, (b) + 0) : (CHECK_BIT_X(n, (b) + 1) \
    : (CHECK_BIT_X(n, (b) + 2) : (CHECK_BIT_X(n, (b) + 3) \
    : (CHECK_BIT_X(n, (b) + 4) : (CHECK_BIT_X(n, (b) + 5) \
    : (CHECK_BIT_X(n, (b) + 6) : (CHECK_BIT_X(n, (b) + 7) \
    : (CHECK_BIT_X(n, (b) + 8) : (CHECK_BIT_X(n, (b) + 9) \
    : (CHECK_BIT_X(n, (b) + 10) : (CHECK_BIT_X(n, (b) + 11) \
    : (CHECK_BIT_X(n, (b) + 12) : (CHECK_BIT_X(n, (b) + 13) \
    : (CHECK_BIT_X(n, (b) + 14) : (CHECK_BIT_X(n, (b) + 15) \
    : (CHECK_BIT_X(n, (b) + 16) : (CHECK_BIT_X(n, (b) + 17) \
    : (CHECK_BIT_X(n, (b) + 18) : (CHECK_BIT_X(n, (b) + 19) \
    : (CHECK_BIT_X(n, (b) + 20) : (CHECK_BIT_X(n, (b) + 21) \
    : (CHECK_BIT_X(n, (b) + 22) : (CHECK_BIT_X(n, (b) + 23) \
    : (CHECK_BIT_X(n, (b) + 24) : (CHECK_BIT_X(n, (b) + 24) \
    : (CHECK_BIT_X(n, (b) + 26) : (CHECK_BIT_X(n, (b) + 26) \
    : (CHECK_BIT_X(n, (b) + 28) : (CHECK_BIT_X(n, (b) + 28) \
    : (CHECK_BIT_X(n, (b) + 30) : (CHECK_BIT_X(n, (b) + 31) \
    : (CHECK_BIT_X(n, (b) + 32) : (CHECK_BIT_X(n, (b) + 33) \
    : (CHECK_BIT_X(n, (b) + 34) : (CHECK_BIT_X(n, (b) + 35) \
    : (CHECK_BIT_X(n, (b) + 36) : (CHECK_BIT_X(n, (b) + 37) \
    : (CHECK_BIT_X(n, (b) + 38) : (CHECK_BIT_X(n, (b) + 39) \
    : (0))))))))))))))))))))))))))))))))))))))))) \
    )


    #define COUNT_BITS_X(n, b) \
    COUNT_BITS_CALC_X(n, b) ? COUNT_BITS_CALC_X(n, b)


    #define COUNT_BITS(n) ( \
    (COUNT_BITS_X(n, 0) : (COUNT_BITS_X(n, 40) \
    : (COUNT_BITS_X(n, 80) : (COUNT_BITS_X(n, 120) \
    : (COUNT_BITS_X(n, 160) : (COUNT_BITS_X(n, 200) \
    : (COUNT_BITS_X(n, 240) : (COUNT_BITS_X(n, 280) \
    : (COUNT_BITS_X(n, 320) : (COUNT_BITS_X(n, 360) \
    : (COUNT_BITS_X(n, 400) : (COUNT_BITS_X(n, 440) \
    : (COUNT_BITS_X(n, 480) : (COUNT_BITS_X(n, 520) \
    : (COUNT_BITS_X(n, 540) : (COUNT_BITS_X(n, 560) \
    : (COUNT_BITS_X(n, 600) : (COUNT_BITS_X(n, 640) \
    : (COUNT_BITS_X(n, 680) : (COUNT_BITS_X(n, 720) \
    : (COUNT_BITS_X(n, 760) : (COUNT_BITS_X(n, 800) \
    : (COUNT_BITS_X(n, 840) : (COUNT_BITS_X(n, 880) \
    : (COUNT_BITS_X(n, 920) : (COUNT_BITS_X(n, 960) \
    : (COUNT_BITS_X(n, 1000) : (COUNT_BITS_X(n, 1040) \
    : (COUNT_BITS_X(n, 1080) : (COUNT_BITS_X(n, 1120) \
    : (COUNT_BITS_X(n, 1160) : (COUNT_BITS_X(n, 1200) \
    : (COUNT_BITS_X(n, 1240) : (COUNT_BITS_X(n, 1260) \
    : (COUNT_BITS_X(n, 1300) : (COUNT_BITS_X(n, 1340) \
    : (COUNT_BITS_X(n, 1380) : (COUNT_BITS_X(n, 1420) \
    : (COUNT_BITS_X(n, 1460) : (COUNT_BITS_X(n, 1500) \
    : (COUNT_BITS_X(n, 1540) : (COUNT_BITS_X(n, 1580) \
    : (0))))))))))))))))))))))))))))))))))))))))))) \
    )




    #if (COUNT_BITS(UCHAR_MAX) == 8)
    typedef signed char int8_type;
    typedef unsigned char uint8_type;
    #else
    # error Platform does not provide an exact 8-bit integer!
    #endif


    #if (COUNT_BITS(USHRT_MAX) == 16)
    typedef signed short int int16_type;
    typedef unsigned char uint16_type;
    #else
    # error Platform does not provide an exact 16-bit integer!
    #endif




    int main(void) {
    printf("%lu\n", COUNT_BITS(18446744073709551615));
    return 0;
    }
    ______________________________________________________________________




    This should go up to 1559 bit integers. Anyway, what do you think?
    Chris M. Thomasson, Jan 16, 2009
    #7
  8. "Peter Nilsson" <> wrote in message
    news:...
    Spiros Bousbouras <> wrote:
    > > ...
    > > A bit more complicated but still (IMO) clearer is
    > >
    > > #define COUNT_BITS(n) ( \
    > > (n) == ( (1 << CHAR_BIT) -1) ? CHAR_BIT : \
    > > (n) == ( (1 << 2*CHAR_BIT) -1) ? 2*CHAR_BIT : \
    > > (n) == ( (1 << 3*CHAR_BIT) -1) ? 3*CHAR_BIT : \


    > There are a few problems with this:
    > n may be a signed type
    > n may be a padded type
    > n may be wider than the left shifted 1 (int)
    > [Even 1<<CHAR_BIT can potentially invoke UB.]


    > <snip>
    > > I have a vague recollection that a while ago someone
    > > posted a macro which did what you wanted (or something
    > > close) and could handle ridiculously large numbers of
    > > bits.


    > Hallvard B Furuseth once posted the following (which
    > I've edited slightly due to line wrap issues)...


    > /* Number of bits in inttype_MAX, or in any (1<<b)-1
    > where 0 <= b < 3E+10 */
    > #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    > /0x3fffffffL %0x3fffffffL *30 + \
    > (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    > 12/((m)%31+3))


    That does not seem to work at all; here is an example:
    ______________________________________________________________________
    #include <limits.h>
    #include <stdio.h>


    #define CHECK_BIT_X(n, b) (((n) >> (b)) == 1) ? (b) + 1


    #define COUNT_BITS_CALC_X(n, b) ( \
    (CHECK_BIT_X(n, (b) + 0) : (CHECK_BIT_X(n, (b) + 1) \
    : (CHECK_BIT_X(n, (b) + 2) : (CHECK_BIT_X(n, (b) + 3) \
    : (CHECK_BIT_X(n, (b) + 4) : (CHECK_BIT_X(n, (b) + 5) \
    : (CHECK_BIT_X(n, (b) + 6) : (CHECK_BIT_X(n, (b) + 7) \
    : (CHECK_BIT_X(n, (b) + 8) : (CHECK_BIT_X(n, (b) + 9) \
    : (CHECK_BIT_X(n, (b) + 10) : (CHECK_BIT_X(n, (b) + 11) \
    : (CHECK_BIT_X(n, (b) + 12) : (CHECK_BIT_X(n, (b) + 13) \
    : (CHECK_BIT_X(n, (b) + 14) : (CHECK_BIT_X(n, (b) + 15) \
    : (CHECK_BIT_X(n, (b) + 16) : (CHECK_BIT_X(n, (b) + 17) \
    : (CHECK_BIT_X(n, (b) + 18) : (CHECK_BIT_X(n, (b) + 19) \
    : (CHECK_BIT_X(n, (b) + 20) : (CHECK_BIT_X(n, (b) + 21) \
    : (CHECK_BIT_X(n, (b) + 22) : (CHECK_BIT_X(n, (b) + 23) \
    : (CHECK_BIT_X(n, (b) + 24) : (CHECK_BIT_X(n, (b) + 24) \
    : (CHECK_BIT_X(n, (b) + 26) : (CHECK_BIT_X(n, (b) + 26) \
    : (CHECK_BIT_X(n, (b) + 28) : (CHECK_BIT_X(n, (b) + 28) \
    : (CHECK_BIT_X(n, (b) + 30) : (CHECK_BIT_X(n, (b) + 31) \
    : (CHECK_BIT_X(n, (b) + 32) : (CHECK_BIT_X(n, (b) + 33) \
    : (CHECK_BIT_X(n, (b) + 34) : (CHECK_BIT_X(n, (b) + 35) \
    : (CHECK_BIT_X(n, (b) + 36) : (CHECK_BIT_X(n, (b) + 37) \
    : (CHECK_BIT_X(n, (b) + 38) : (CHECK_BIT_X(n, (b) + 39) \
    : (0))))))))))))))))))))))))))))))))))))))))) \
    )


    #define COUNT_BITS_X(n, b) \
    COUNT_BITS_CALC_X(n, b) ? COUNT_BITS_CALC_X(n, b)


    #define COUNT_BITS(n) ( \
    (COUNT_BITS_X(n, 0) : (COUNT_BITS_X(n, 40) \
    : (COUNT_BITS_X(n, 80) : (COUNT_BITS_X(n, 120) \
    : (COUNT_BITS_X(n, 160) : (COUNT_BITS_X(n, 200) \
    : (COUNT_BITS_X(n, 240) : (COUNT_BITS_X(n, 280) \
    : (COUNT_BITS_X(n, 320) : (COUNT_BITS_X(n, 360) \
    : (COUNT_BITS_X(n, 400) : (COUNT_BITS_X(n, 440) \
    : (COUNT_BITS_X(n, 480) : (COUNT_BITS_X(n, 520) \
    : (COUNT_BITS_X(n, 540) : (COUNT_BITS_X(n, 560) \
    : (COUNT_BITS_X(n, 600) : (COUNT_BITS_X(n, 640) \
    : (COUNT_BITS_X(n, 680) : (COUNT_BITS_X(n, 720) \
    : (COUNT_BITS_X(n, 760) : (COUNT_BITS_X(n, 800) \
    : (COUNT_BITS_X(n, 840) : (COUNT_BITS_X(n, 880) \
    : (COUNT_BITS_X(n, 920) : (COUNT_BITS_X(n, 960) \
    : (COUNT_BITS_X(n, 1000) : (COUNT_BITS_X(n, 1040) \
    : (COUNT_BITS_X(n, 1080) : (COUNT_BITS_X(n, 1120) \
    : (COUNT_BITS_X(n, 1160) : (COUNT_BITS_X(n, 1200) \
    : (COUNT_BITS_X(n, 1240) : (COUNT_BITS_X(n, 1260) \
    : (COUNT_BITS_X(n, 1300) : (COUNT_BITS_X(n, 1340) \
    : (COUNT_BITS_X(n, 1380) : (COUNT_BITS_X(n, 1420) \
    : (COUNT_BITS_X(n, 1460) : (COUNT_BITS_X(n, 1500) \
    : (COUNT_BITS_X(n, 1540) : (COUNT_BITS_X(n, 1580) \
    : (0))))))))))))))))))))))))))))))))))))))))))) \
    )




    #if (COUNT_BITS(UCHAR_MAX) == 8)
    typedef signed char int8_type;
    typedef unsigned char uint8_type;
    #else
    # error Platform does not provide an exact 8-bit integer!
    #endif


    #if (COUNT_BITS(USHRT_MAX) == 16)
    typedef signed short int int16_type;
    typedef unsigned char uint16_type;
    #else
    # error Platform does not provide an exact 16-bit integer!
    #endif


    #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    /0x3fffffffL %0x3fffffffL *30 + \
    (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    12/((m)%31+3))


    #if (IMAX_BITS(UINT_MAX) == 32)
    typedef signed char int32_type;
    typedef unsigned char uint32_type;
    #else
    # error Platform does not provide an exact 32-bit integer!
    #endif




    int main(void) {
    printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551615));
    printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551615));


    printf("IMAX_BITS - %lu\n", IMAX_BITS(184467440737095516));
    printf("COUNT_BITS - %lu\n\n", COUNT_BITS(184467440737095516));


    printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551));
    printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551));


    return 0;
    }
    ______________________________________________________________________






    Here is the output I get on a 32-bit P4:


    IMAX_BITS - 64
    COUNT_BITS - 64

    IMAX_BITS - 858993464
    COUNT_BITS - 58

    IMAX_BITS - 39
    COUNT_BITS - 55




    What am I doing wrong?
    Chris M. Thomasson, Jan 16, 2009
    #8
  9. Peter Nilsson <> writes:

    <snip>
    > Hallvard B Furuseth once posted the following (which
    > I've edited slightly due to line wrap issues)...
    >
    > /* Number of bits in inttype_MAX, or in any (1<<b)-1
    > where 0 <= b < 3E+10 */


    Unless I am miss-reading the notation, that should probably be "where
    0 <= (1<<b) < 3E+10".

    > #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    > /0x3fffffffL %0x3fffffffL *30 + \
    > (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    > 12/((m)%31+3))


    Was there an explanation? :)

    --
    Ben.
    Ben Bacarisse, Jan 16, 2009
    #9
  10. "Chris M. Thomasson" <> writes:

    > "Peter Nilsson" <> wrote in message

    <snip>
    >> Hallvard B Furuseth once posted the following (which
    >> I've edited slightly due to line wrap issues)...

    >
    >> /* Number of bits in inttype_MAX, or in any (1<<b)-1
    >> where 0 <= b < 3E+10 */
    >> #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    >> /0x3fffffffL %0x3fffffffL *30 + \
    >> (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    >> 12/((m)%31+3))

    >
    > That does not seem to work at all; here is an example:

    <snip>
    > int main(void) {
    > printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551615));
    > printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551615));
    >
    > printf("IMAX_BITS - %lu\n", IMAX_BITS(184467440737095516));
    > printf("COUNT_BITS - %lu\n\n", COUNT_BITS(184467440737095516));
    >
    > printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551));
    > printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551));
    >
    > return 0;
    > }
    > ______________________________________________________________________
    >
    > Here is the output I get on a 32-bit P4:
    >
    > IMAX_BITS - 64
    > COUNT_BITS - 64
    >
    > IMAX_BITS - 858993464
    > COUNT_BITS - 58
    >
    > IMAX_BITS - 39
    > COUNT_BITS - 55
    >
    > What am I doing wrong?


    IMAX_BITS expects a number of the form (1 << n) - 1. I.e. one less
    than a (non-negative) integer power of 2. Only the first example fits
    that pattern.

    --
    Ben.
    Ben Bacarisse, Jan 16, 2009
    #10
  11. "Chris M. Thomasson" <> wrote in message
    news:vLSbl.12177$...

    Here is the code with a slight tweak:
    ___________________________________________________________________
    #include <limits.h>
    #include <stdio.h>


    #define CHECK_BIT_X(n, b) (((n) >> (b)) == 1UL) ? (b) + 1UL


    #define COUNT_BITS_CALC_X(n, b) ( \
    (CHECK_BIT_X(n, (b) + 0UL) : (CHECK_BIT_X(n, (b) + 1UL) \
    : (CHECK_BIT_X(n, (b) + 2UL) : (CHECK_BIT_X(n, (b) + 3UL) \
    : (CHECK_BIT_X(n, (b) + 4UL) : (CHECK_BIT_X(n, (b) + 5UL) \
    : (CHECK_BIT_X(n, (b) + 6UL) : (CHECK_BIT_X(n, (b) + 7UL) \
    : (CHECK_BIT_X(n, (b) + 8UL) : (CHECK_BIT_X(n, (b) + 9UL) \
    : (CHECK_BIT_X(n, (b) + 10UL) : (CHECK_BIT_X(n, (b) + 11UL) \
    : (CHECK_BIT_X(n, (b) + 12UL) : (CHECK_BIT_X(n, (b) + 13UL) \
    : (CHECK_BIT_X(n, (b) + 14UL) : (CHECK_BIT_X(n, (b) + 15UL) \
    : (CHECK_BIT_X(n, (b) + 16UL) : (CHECK_BIT_X(n, (b) + 17UL) \
    : (CHECK_BIT_X(n, (b) + 18UL) : (CHECK_BIT_X(n, (b) + 19UL) \
    : (CHECK_BIT_X(n, (b) + 20UL) : (CHECK_BIT_X(n, (b) + 21UL) \
    : (CHECK_BIT_X(n, (b) + 22UL) : (CHECK_BIT_X(n, (b) + 23UL) \
    : (CHECK_BIT_X(n, (b) + 24UL) : (CHECK_BIT_X(n, (b) + 24UL) \
    : (CHECK_BIT_X(n, (b) + 26UL) : (CHECK_BIT_X(n, (b) + 26UL) \
    : (CHECK_BIT_X(n, (b) + 28UL) : (CHECK_BIT_X(n, (b) + 28UL) \
    : (CHECK_BIT_X(n, (b) + 30UL) : (CHECK_BIT_X(n, (b) + 31UL) \
    : (CHECK_BIT_X(n, (b) + 32UL) : (CHECK_BIT_X(n, (b) + 33UL) \
    : (CHECK_BIT_X(n, (b) + 34UL) : (CHECK_BIT_X(n, (b) + 35UL) \
    : (CHECK_BIT_X(n, (b) + 36UL) : (CHECK_BIT_X(n, (b) + 37UL) \
    : (CHECK_BIT_X(n, (b) + 38UL) : (CHECK_BIT_X(n, (b) + 39UL) \
    : (0))))))))))))))))))))))))))))))))))))))))) \
    )


    #define COUNT_BITS_X(n, b) \
    COUNT_BITS_CALC_X(n, b) ? COUNT_BITS_CALC_X(n, b)


    #define COUNT_BITS(n) ( \
    (COUNT_BITS_X(n, 0UL) : (COUNT_BITS_X(n, 40UL) \
    : (COUNT_BITS_X(n, 80UL) : (COUNT_BITS_X(n, 120UL) \
    : (COUNT_BITS_X(n, 160UL) : (COUNT_BITS_X(n, 200UL) \
    : (COUNT_BITS_X(n, 240UL) : (COUNT_BITS_X(n, 280UL) \
    : (COUNT_BITS_X(n, 320UL) : (COUNT_BITS_X(n, 360UL) \
    : (COUNT_BITS_X(n, 400UL) : (COUNT_BITS_X(n, 440UL) \
    : (COUNT_BITS_X(n, 480UL) : (COUNT_BITS_X(n, 520UL) \
    : (COUNT_BITS_X(n, 540UL) : (COUNT_BITS_X(n, 560UL) \
    : (COUNT_BITS_X(n, 600UL) : (COUNT_BITS_X(n, 640UL) \
    : (COUNT_BITS_X(n, 680UL) : (COUNT_BITS_X(n, 720UL) \
    : (COUNT_BITS_X(n, 760UL) : (COUNT_BITS_X(n, 800UL) \
    : (COUNT_BITS_X(n, 840UL) : (COUNT_BITS_X(n, 880UL) \
    : (COUNT_BITS_X(n, 920UL) : (COUNT_BITS_X(n, 960UL) \
    : (COUNT_BITS_X(n, 1000UL) : (COUNT_BITS_X(n, 1040UL) \
    : (COUNT_BITS_X(n, 1080UL) : (COUNT_BITS_X(n, 1120UL) \
    : (COUNT_BITS_X(n, 1160UL) : (COUNT_BITS_X(n, 1200UL) \
    : (COUNT_BITS_X(n, 1240UL) : (COUNT_BITS_X(n, 1260UL) \
    : (COUNT_BITS_X(n, 1300UL) : (COUNT_BITS_X(n, 1340UL) \
    : (COUNT_BITS_X(n, 1380UL) : (COUNT_BITS_X(n, 1420UL) \
    : (COUNT_BITS_X(n, 1460UL) : (COUNT_BITS_X(n, 1500UL) \
    : (COUNT_BITS_X(n, 1540UL) : (COUNT_BITS_X(n, 1580UL) \
    : (0))))))))))))))))))))))))))))))))))))))))))) \
    )




    #if (COUNT_BITS(UCHAR_MAX) == 8UL)
    typedef signed char int8_type;
    typedef unsigned char uint8_type;
    #else
    # error Platform does not provide an exact 8-bit integer!
    #endif


    #if (COUNT_BITS(USHRT_MAX) == 16UL)
    typedef signed short int int16_type;
    typedef unsigned short int uint16_type;
    #else
    # error Platform does not provide an exact 16-bit integer!
    #endif


    #if (COUNT_BITS(UINT_MAX) == 32UL)
    typedef signed int int32_type;
    typedef unsigned int uint32_type;
    #else
    # error Platform does not provide an exact 32-bit integer!
    #endif


    #if (COUNT_BITS(18446744073709551615) == 64UL)
    # if ! defined (_MSC_VER)
    typedef signed long long int int64_type;
    typedef unsigned long long int uint64_type;
    # else
    typedef signed __int64 int64_type;
    typedef unsigned __int64 uint64_type;
    # endif
    #else
    # error Platform does not provide an exact 64-bit integer!
    #endif




    int main(void) {
    printf("COUNT_BITS 8 - %lu\n\n",
    (unsigned long int)(sizeof(int8_type) * CHAR_BIT));

    printf("COUNT_BITS 16 - %lu\n\n",
    (unsigned long int)(sizeof(int16_type) * CHAR_BIT));

    printf("COUNT_BITS 32 - %lu\n\n",
    (unsigned long int)(sizeof(int32_type) * CHAR_BIT));

    printf("COUNT_BITS 64 - %lu\n\n",
    (unsigned long int)(COUNT_BITS(18446744073709551615)));

    printf("COUNT_BITS 63 - %lu\n\n",
    (unsigned long int)(COUNT_BITS(9223372036854775807)));

    return 0;
    }
    ___________________________________________________________________





    Your compiler needs to support 64-bit integers in order to properly count
    the last two large numbers.




    > This should go up to 1559 bit integers. Anyway, what do you think?


    Humm...
    Chris M. Thomasson, Jan 16, 2009
    #11
  12. There was a bug in the `COUNT_BITS_CALC_X' macro. The number sequence had a
    bad value. Here is correction:




    #define COUNT_BITS_CALC_X(n, b) ( \
    (CHECK_BIT_X(n, (b) + 0UL) : (CHECK_BIT_X(n, (b) + 1UL) \
    : (CHECK_BIT_X(n, (b) + 2UL) : (CHECK_BIT_X(n, (b) + 3UL) \
    : (CHECK_BIT_X(n, (b) + 4UL) : (CHECK_BIT_X(n, (b) + 5UL) \
    : (CHECK_BIT_X(n, (b) + 6UL) : (CHECK_BIT_X(n, (b) + 7UL) \
    : (CHECK_BIT_X(n, (b) + 8UL) : (CHECK_BIT_X(n, (b) + 9UL) \
    : (CHECK_BIT_X(n, (b) + 10UL) : (CHECK_BIT_X(n, (b) + 11UL) \
    : (CHECK_BIT_X(n, (b) + 12UL) : (CHECK_BIT_X(n, (b) + 13UL) \
    : (CHECK_BIT_X(n, (b) + 14UL) : (CHECK_BIT_X(n, (b) + 15UL) \
    : (CHECK_BIT_X(n, (b) + 16UL) : (CHECK_BIT_X(n, (b) + 17UL) \
    : (CHECK_BIT_X(n, (b) + 18UL) : (CHECK_BIT_X(n, (b) + 19UL) \
    : (CHECK_BIT_X(n, (b) + 20UL) : (CHECK_BIT_X(n, (b) + 21UL) \
    : (CHECK_BIT_X(n, (b) + 22UL) : (CHECK_BIT_X(n, (b) + 23UL) \
    : (CHECK_BIT_X(n, (b) + 24UL) : (CHECK_BIT_X(n, (b) + 25UL) \
    : (CHECK_BIT_X(n, (b) + 26UL) : (CHECK_BIT_X(n, (b) + 27UL) \
    : (CHECK_BIT_X(n, (b) + 28UL) : (CHECK_BIT_X(n, (b) + 29UL) \
    : (CHECK_BIT_X(n, (b) + 30UL) : (CHECK_BIT_X(n, (b) + 31UL) \
    : (CHECK_BIT_X(n, (b) + 32UL) : (CHECK_BIT_X(n, (b) + 33UL) \
    : (CHECK_BIT_X(n, (b) + 34UL) : (CHECK_BIT_X(n, (b) + 35UL) \
    : (CHECK_BIT_X(n, (b) + 36UL) : (CHECK_BIT_X(n, (b) + 37UL) \
    : (CHECK_BIT_X(n, (b) + 38UL) : (CHECK_BIT_X(n, (b) + 39UL) \
    : (0))))))))))))))))))))))))))))))))))))))))) \
    )




    Sorry about that non-sense!


    ;^(...
    Chris M. Thomasson, Jan 16, 2009
    #12
  13. Chris M. Thomasson

    Bartc Guest

    "Chris M. Thomasson" <> wrote in message
    news:2XObl.32003$...
    > How "reliable" is the following code:
    > ____________________________________________________________

    ....
    ____________________________________________________________

    Your code gave some warnings about improper shifts.

    > I am tinkering around with different ways to use the pre-processor to
    > determine exact number of bits in integral types. Is there a much better
    > way to do this? What am I missing here?


    Perhaps I'm missing the point but I would just use code like the following
    for each platform:

    #define CHAR_BITS 8
    #define SHORT_BITS 16
    #define INT_BITS 32
    #define LONG_BITS 32
    #define INT16_BITS 16

    For example "bitsizes.h". Perhaps created by a utility that you run one once
    on each platform, which then works out the figures during (it's) runtime.

    --
    Bartc
    Bartc, Jan 16, 2009
    #13
  14. Chris M. Thomasson

    Eric Sosman Guest

    Chris M. Thomasson wrote:
    > "Eric Sosman" <> wrote in message
    > news:1232061810.681510@news1nwk...
    >> Chris M. Thomasson wrote:
    >>> How "reliable" is the following code:
    >>> [... see up-thread ...]

    >>
    >> "Reliable" in the face of what threats or eventualities?
    >> It doesn't work in the presence of padding bits, it might not
    >> work for UINTMAX_MAX or INTMAX_MAX, it definitely won't work for
    >> floating-point types ... I'm not sure what realm of possibilities
    >> you're concerned about.

    >
    > I would only ever pass the following values to the `COUNT_BITS' macro:
    >
    >
    > UCHAR_MAX
    > USHRT_MAX
    > UINT_MAX
    > ULONG_MAX
    >
    >
    > I am assuming that the number of bits it takes to hold any of those
    > values will be a multiple of `CHAR_BIT'.


    Okay, so you're also assuming that the number of padding
    bits is also a multiple of CHAR_BIT. That is, you're assuming
    that if there's any padding it's in byte-sized chunks.

    Note that shifting by `sizeof(unsigned long)*CHAR_BIT' may
    be undefined for C99 and *is* undefined for C90.

    > [...]
    >> The "much better way" -- well, can you formulate your questions
    >> in terms of ranges rather than in terms of logarithms? That is, how
    >> badly do you need actual bit counts?

    > [...]
    > The `compiler/vendor/.../core.h' files are required to define some types
    > that have exact number of bits. If I know the compiler, I will use
    > specific extensions to get the job done. However, if the compiler is
    > unknown, well, I need to at least "attempt" to render the correctly
    > sized types. I need this to all be performed at compile time.


    The task of choosing an N-bit type for known N is much
    easier than that of finding the number of bits in a type T.
    For C90:

    #include <limits.h>
    #if UCHAR_MAX == 0xFFFFF
    typedef unsigned char u20;
    #elif USHRT_MAX == 0xFFFFF
    typedef unsigned short u20;
    #elif UINT_MAX == 0xFFFFF
    typedef unsigned int u20;
    #elif ULONG_MAX == 0xFFFFF
    /* necessarily false; just here to show the pattern */
    typedef unsigned long u20;
    #else
    #error "No 20-bit type!"
    #endif

    For C99 the repertoire of integer types is open-ended
    and you can't enumerate and test them this way. However, C99
    has a helpful header of its own:

    #include <stdint.h>
    #ifdef UINT20_MAX
    typedef uint20_t u20;
    #else
    #error "No 20-bit type!"
    #endif

    --
    Eric Sosman
    lid
    Eric Sosman, Jan 16, 2009
    #14
  15. Chris M. Thomasson

    Kaz Kylheku Guest

    On 2009-01-16, Bartc <> wrote:
    >
    > "Chris M. Thomasson" <> wrote in message
    > news:2XObl.32003$...
    >> How "reliable" is the following code:
    >> ____________________________________________________________

    > ...
    > ____________________________________________________________
    >
    > Your code gave some warnings about improper shifts.
    >
    >> I am tinkering around with different ways to use the pre-processor to
    >> determine exact number of bits in integral types. Is there a much better
    >> way to do this? What am I missing here?

    >
    > Perhaps I'm missing the point but I would just use code like the following
    > for each platform:
    >
    > #define CHAR_BITS 8


    What's wrong with CHAR_BIT from <limits.h>?

    I get it, you're new.

    > #define SHORT_BITS 16
    > #define INT_BITS 32
    > #define LONG_BITS 32
    > #define INT16_BITS 16


    Would INT16_BITS be anything other than 16? Are you including paddding bits
    that don't contribute to the representation of value?

    > For example "bitsizes.h". Perhaps created by a utility that you run one once
    > on each platform, which then works out the figures during (it's) runtime.


    How do you run this utility if you're cross-compiling?
    Kaz Kylheku, Jan 16, 2009
    #15
  16. Chris M. Thomasson

    Bartc Guest

    "Kaz Kylheku" <> wrote in message
    news:...
    > On 2009-01-16, Bartc <> wrote:


    >>> I am tinkering around with different ways to use the pre-processor to
    >>> determine exact number of bits in integral types. Is there a much better
    >>> way to do this? What am I missing here?

    >>
    >> Perhaps I'm missing the point but I would just use code like the
    >> following
    >> for each platform:
    >>
    >> #define CHAR_BITS 8

    >
    > What's wrong with CHAR_BIT from <limits.h>?


    I snipped too much code. The OP seemed to be trying to calculate these,
    which seem to include bits in char and int16:

    "Chris M. Thomasson" <> wrote in message
    news:2XObl.32003$...
    > (unsigned long int)COUNT_BITS(UCHAR_MAX),
    > (unsigned long int)COUNT_BITS(USHRT_MAX),
    > (unsigned long int)COUNT_BITS(UINT_MAX),
    > (unsigned long int)COUNT_BITS(ULONG_MAX),
    > (unsigned long int)(CHAR_BIT * sizeof(int16_type))


    > I get it, you're new.


    In a way..

    >
    >> #define SHORT_BITS 16
    >> #define INT_BITS 32
    >> #define LONG_BITS 32
    >> #define INT16_BITS 16

    >
    > Would INT16_BITS be anything other than 16? Are you including paddding
    > bits
    > that don't contribute to the representation of value?


    I don't know about padding bits. If they need to be included then those
    defines (or the bit of code I suggested) need tweaking.

    >
    >> For example "bitsizes.h". Perhaps created by a utility that you run one
    >> once
    >> on each platform, which then works out the figures during (it's) runtime.

    >
    > How do you run this utility if you're cross-compiling?


    With difficulty. Or just do it manually if it's impossible. Even the
    lowliest microprocessor must have some LED (or some I/O pin) it can flash N
    times to indicate how many bits in a C word.

    --
    Bartc
    Bartc, Jan 16, 2009
    #16
  17. On 16 Jan, 04:42, Ben Bacarisse <> wrote:
    > Peter Nilsson <> writes:
    >
    > <snip>
    >
    > > Hallvard B Furuseth once posted the following (which
    > > I've edited slightly due to line wrap issues)...

    >
    > > /* Number of bits in inttype_MAX, or in any (1<<b)-1
    > > where 0 <= b < 3E+10 */

    >
    > Unless I am miss-reading the notation, that should probably be "where
    > 0 <= (1<<b) < 3E+10".


    Perhaps you are misreading the notation or perhaps you think
    it's too good to be true but the macro really can handle numbers
    of the form (1<<b) - 1 where 0 <= b < 30 * ( (1<<30) - 1)
    Quite ingenious.

    > > #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    > > /0x3fffffffL %0x3fffffffL *30 + \
    > > (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    > > 12/((m)%31+3))

    >
    > Was there an explanation? :)


    http://tinyurl.com/bfeddm
    Spiros Bousbouras, Jan 22, 2009
    #17
  18. Spiros Bousbouras <> writes:

    > On 16 Jan, 04:42, Ben Bacarisse <> wrote:
    >> Peter Nilsson <> writes:
    >>
    >> <snip>
    >>
    >> > Hallvard B Furuseth once posted the following (which
    >> > I've edited slightly due to line wrap issues)...

    >>
    >> > /* Number of bits in inttype_MAX, or in any (1<<b)-1
    >> > where 0 <= b < 3E+10 */

    >>
    >> Unless I am miss-reading the notation, that should probably be "where
    >> 0 <= (1<<b) < 3E+10".

    >
    > Perhaps you are misreading the notation


    No, it seems I was not misreading it, but my suggested correction is
    way off.

    > or perhaps you think
    > it's too good to be true but the macro really can handle numbers
    > of the form (1<<b) - 1 where 0 <= b < 30 * ( (1<<30) - 1)


    Not "too good to be true" just an unlikely bound on a bit-counting
    algorithm! I was, none the less, mistaken.

    > Quite ingenious.
    >
    >> > #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
    >> > /0x3fffffffL %0x3fffffffL *30 + \
    >> > (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
    >> > 12/((m)%31+3))

    >>
    >> Was there an explanation? :)

    >
    > http://tinyurl.com/bfeddm


    Thanks for finding that.

    --
    Ben.
    Ben Bacarisse, Jan 22, 2009
    #18
    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. Ken Philips
    Replies:
    1
    Views:
    436
    Anthony Borla
    Feb 7, 2005
  2. Vish
    Replies:
    3
    Views:
    679
    Lawrence Kirby
    Apr 29, 2005
  3. Replies:
    24
    Views:
    1,082
    Keith Thompson
    Mar 20, 2007
  4. brahatha
    Replies:
    1
    Views:
    643
  5. sarahh

    sum of 64 bits using 32 bits cpu

    sarahh, May 13, 2008, in forum: C Programming
    Replies:
    18
    Views:
    519
    Richard Tobin
    May 14, 2008
Loading...

Share This Page