Portable Test for long long Support

Discussion in 'C Programming' started by Mark Shelor, Oct 24, 2003.

  1. Mark Shelor

    Mark Shelor Guest

    Problem: find a portable way to determine whether a compiler supports
    the "long long" type of C99.

    I thought I had this one solved with the following code:


    #include <limits.h>


    #ifdef ULONG_LONG_MAX

    /* 64-bit code */

    #endif


    This seemed to work on most platforms until I compiled today under
    Mandrake linux i586 (gcc 3.2.2). What's odd is that this compiler
    supports the "long long" type, yet the 64-bit code didn't get included.

    Any ideas? Is there a "standard" way to test whether a C compiler
    supports the C99 types?

    Mark
     
    Mark Shelor, Oct 24, 2003
    #1
    1. Advertising

  2. On Thu, 23 Oct 2003, Mark Shelor wrote:
    >
    > Problem: find a portable way to determine whether a compiler supports
    > the "long long" type of C99.
    >
    > I thought I had this one solved with the following code:
    >
    > #include <limits.h>
    >
    > #ifdef ULONG_LONG_MAX


    I believe the correct macro name is ULLONG_MAX (and the signed
    equivalents would be LLONG_MAX and LLONG_MIN).

    > /* 64-bit code */
    >
    > #endif


    > This seemed to work on most platforms until I compiled today under
    > Mandrake linux i586 (gcc 3.2.2). What's odd is that this compiler
    > supports the "long long" type, yet the 64-bit code didn't get included.
    >
    > Any ideas? Is there a "standard" way to test whether a C compiler
    > supports the C99 types?


    That way looks like the safest way to me. But, as another thread
    pointed out recently, just because your 'gcc' supports

    long long int foo;

    doesn't necessarily mean that your version of 'libc' supports

    printf("%lld\n", foo);

    You'll need to test all the relevant library functions as well as
    the core language support. And that will probably get painful.
    It might be easier in some cases to simply let the guy compiling
    the program set a macro through -DUSE_LONG_LONG or whatever, and
    let *him* take the blame for incomplete 'long long' support. :)
    I.e., skip the <limits.h> test and just write

    #if USE_LONG_LONG
    [...stuff...]
    #else
    [...stuff using 'long' only...]
    #endif


    My $.02,
    -Arthur
     
    Arthur J. O'Dwyer, Oct 24, 2003
    #2
    1. Advertising

  3. Mark Shelor

    Chris Torek Guest

    In article <>,
    Mark Shelor <> wrote:
    >Problem: find a portable way to determine whether a compiler supports
    >the "long long" type of C99.
    >
    >I thought I had this one solved with the following code:
    >
    >#include <limits.h>
    >
    >#ifdef ULONG_LONG_MAX

    [snippage]

    Actually, the C99 name for the macros are LLONG_MIN, LLONG_MAX,
    and ULLONG_MAX respectively.

    You may encounter systems that have (partial or complete) support
    for "long long" but do not have the defines, simply because those
    systems are not (yet?) C99-conformant and no effort was put into
    updating the headers.

    In some ways this is related to the hypothetical situation of an
    otherwise C89-conformant system that fails to define __STDC__ as
    1, and therefore fails to conform. :)
    --
    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://67.40.109.61/torek/index.html (for the moment)
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Oct 24, 2003
    #3
  4. Mark Shelor <> writes:
    > Problem: find a portable way to determine whether a compiler supports
    > the "long long" type of C99.
    >
    > I thought I had this one solved with the following code:
    >
    >
    > #include <limits.h>
    >
    >
    > #ifdef ULONG_LONG_MAX
    >
    > /* 64-bit code */
    >
    > #endif
    >
    >
    > This seemed to work on most platforms until I compiled today under
    > Mandrake linux i586 (gcc 3.2.2). What's odd is that this compiler
    > supports the "long long" type, yet the 64-bit code didn't get included.
    >
    > Any ideas? Is there a "standard" way to test whether a C compiler
    > supports the C99 types?


    As others have pointed out, the relevant macros are LLONG_MAX and
    ULLONG_MAX. But since "long long" appeared as an extension before it
    was blessed by the C99 standard, there may be implementations that
    provide long long but don't have LLONG_MAX and ULLONG_MAX.

    You might consider testing during configuration rather than during
    compilation. For example, you might write a small C program that
    declares a long long variable and appends the line

    #define HAVE_LONG_LONG

    to one of your application header files. Try to compile and run the
    program. If long long is supported, it will run and append the line;
    if it's not, it will fail to compile, and HAVE_LONG_LONG won't be
    defined for your application.

    BTW, are you really looking for type long long or for a 64-bit type?
    Type long long is guaranteed to be at least 64 bits, but there could
    be implementations that don't define long long, but that have 64-bit
    longs. Consider using uint64_t or uint_least64_t from <stdint.h> If
    your implementation doesn't have <stdint.h>, Doug Gwyn has written a
    reasonably portable C90-compatible implementation of it; see
    <http://www.lysator.liu.se/c/q8/index.html>.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
    Schroedinger does Shakespeare: "To be *and* not to be"
     
    Keith Thompson, Oct 24, 2003
    #4
  5. Mark Shelor

    Mark Shelor Guest

    Keith Thompson wrote:

    > Mark Shelor <> writes:
    >
    >>Problem: find a portable way to determine whether a compiler supports
    >>the "long long" type of C99.
    >>

    > As others have pointed out, the relevant macros are LLONG_MAX and
    > ULLONG_MAX. But since "long long" appeared as an extension before it
    > was blessed by the C99 standard, there may be implementations that
    > provide long long but don't have LLONG_MAX and ULLONG_MAX.
    >
    > BTW, are you really looking for type long long or for a 64-bit type?
    > Type long long is guaranteed to be at least 64 bits, but there could
    > be implementations that don't define long long, but that have 64-bit
    > longs. Consider using uint64_t or uint_least64_t from <stdint.h> If
    > your implementation doesn't have <stdint.h>, Doug Gwyn has written a
    > reasonably portable C90-compatible implementation of it; see
    > <http://www.lysator.liu.se/c/q8/index.html>.



    Thanks Keith, Arthur, Chris for the helpful replies.

    Yes, I did try using ULLONG_MAX earlier in the day, but had no luck
    there either. Oddly, when I grep'd on ULONG_LONG_MAX in the
    /usr/include subdirectories, the response I got was

    $ grep ULONG_LONG_MAX `find /usr/include -print`
    /usr/include/limits.h:# define ULLONG_MAX ULONG_LONG_MAX

    However, since this #define was nested within other #ifdef's that
    apparently get excluded during the compile, the token ULLONG_MAX didn't
    show up as being defined.

    If I remove my original conditional compilation directive, and simply go
    ahead and include the 64-bit code (with unsigned long long's),
    everything compiles and runs just fine. So, this has me scratching my
    head a bit.

    I'm using this #ifdef in a package I wrote for CPAN. It's a C
    implementation (wrapped in a Perl module) of NIST's Secure Hash
    Algorithms (SHA-1/256/384/512). Basically, the latter two (384/512) use
    64-bit operations, so I note in my documentation that run-time code for
    them won't exist if one's native compiler lacks support for long long's.
    However, the package will still compile and run just fine.

    Since this package gets downloaded, compiled, and installed by lots of
    people with C compilers of unknown capability, I've written the code to
    be as vanilla and portable as possible. What I DON'T want to have
    happen is for a person's compile to crash if his compiler doesn't happen
    to support long long's. It's acceptable in those circumstances for the
    package to omit support for SHA-384 and SHA-512, which fortunately
    aren't really crucial in the near-term anyway.

    Yet another oddity is the fact that the 64-bit code gets included when I
    compile it under the automake facility that's provided as part of the
    Perl packaging utility (h2xs). However, when I compile it as a
    standalone C program with a simple test driver, the 64-bit code is
    missing. I don't have the patience to wade through the myriad compiler
    options and define's used by h2xs to figure out what's going on! :)

    Regards, Mark
     
    Mark Shelor, Oct 24, 2003
    #5
  6. On Fri, 24 Oct 2003, Mark Shelor wrote:
    >
    > Keith Thompson wrote:
    > >
    > > BTW, are you really looking for type long long or for a 64-bit type?


    > I'm using this #ifdef in a package I wrote for CPAN. It's a C
    > implementation (wrapped in a Perl module) of NIST's Secure Hash
    > Algorithms (SHA-1/256/384/512). Basically, the latter two (384/512) use
    > 64-bit operations, so I note in my documentation that run-time code for
    > them won't exist if one's native compiler lacks support for long long's.
    > However, the package will still compile and run just fine.
    >
    > Since this package gets downloaded, compiled, and installed by lots of
    > people with C compilers of unknown capability, I've written the code to
    > be as vanilla and portable as possible.


    If you wanted to be really nice, you could write (or better, Google)
    a couple of routines for 64-bit multiplication, rotation, or whatever
    using pairs of 32-bit variables, and then write a 32-bit version of
    your code that way, for people whose machines don't support 64-bit
    stuff on a hardware level but who still want to use your module.

    #ifdef HAVE_LONG_LONG
    unsigned long long x = 0x238776a8f887ea60;
    x <<= 6;
    x += 17;
    #else
    unsigned int xh = 0x238776a8;
    unsigned int xl = 0xf887ea60;
    xh <<= 6;
    xh |= xl >> (32-6);
    xl <<= 6;
    ull_add(&xh, &xl, 0, 17);
    #endif


    HTH,
    -Arthur
     
    Arthur J. O'Dwyer, Oct 24, 2003
    #6
    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. Eli Bendersky
    Replies:
    1
    Views:
    1,180
    Mike Treseler
    Mar 1, 2006
  2. Nick Zdunic
    Replies:
    0
    Views:
    929
    Nick Zdunic
    Nov 5, 2003
  3. George Marsaglia

    Assigning unsigned long to unsigned long long

    George Marsaglia, Jul 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    706
    Eric Sosman
    Jul 8, 2003
  4. Replies:
    7
    Views:
    930
  5. Skybuck Flying

    Call oddities: &Test() vs &Test vs Test

    Skybuck Flying, Oct 4, 2009, in forum: C Programming
    Replies:
    1
    Views:
    726
    Skybuck Flying
    Oct 4, 2009
Loading...

Share This Page