Distinguishing between long and long long on an LP64 machine?

View: New views
3 Messages — Rating Filter:   Alert me  

Distinguishing between long and long long on an LP64 machine?

by Mark Dickinson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Suppose that I have a signed integer type coming from a header
file, and that I already know that this integer type is a 64-bit
type. (Think off_t, for example.) If I'm using gcc on a machine
where both long and long long also have 64 bits, is there any
simple C99 (+ gcc extension) code that will allow me to figure
out whether this type is ultimately defined as long or long long?

The original motivation was to avoid gcc -Wall warnings when
doing:

off_t my_offset;
...
printf("%lld", my_offset);

If off_t is defined as long rather than long long then this will
give a warning, even though the sizes match.  (So of course,
this actually gives a programmatic way to distinguish: have
a configure script do a test compilation with -Wall -Werror.
But I'm looking for a simple C expression or function that
could detect the difference.)

It seems that some LP64 platforms (e.g., OS X 10.6) define
off_t to be long long, while others (e.g., Linux/x86_64, or at least
the three different flavours of Linux that I tested) define off_t
to be long.

Of course, the solution to avoiding printf warnings is as easy
as adding a cast:

printf("%lld", (long long)my_offset);

so in this particular motivating case there isn't really
any problem.  But I'm still curious to know
whether there's a simple way for a gcc *user* to distinguish
between long and long long when both are 64 bits.  typeof
doesn't seem to help here.  I guess I'm really after some
imaginary extension 'rank_of' that lets me do

if (rank_of(off_t) == rank_of(long long))
< code using %lld >
else
< code using %ld >
...

Mark

Re: Distinguishing between long and long long on an LP64 machine?

by John (Eljay) Love-Jensen :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Mark,

> If I'm using gcc on a machine where both long and long long also have 64 bits,
> is there any simple C99 (+ gcc extension) code that will allow me to figure
> out whether this type is ultimately defined as long or long long?

If you are using C++, yes.  If you are using C... I don't think so.

For your example, this is how I do it:

off_t my_offset;
//...
printf("%lld", (long long)my_offset);

Why?  Because there is no printf format specifier for off_t:

printf("%{off_t}d", my_offset);

And *that* is really the problem you are running into.  (If I recall
correctly, C/C++ Users Journal had published an article on extensible printf
called eprintf, and there you could register off_t handling.)

If you are using C99, then you could do it this way:

#include <inttypes.h>
//...
off_t my_offset;
//...
printf("%"PRId64, (int64_t)my_offset);

That's even more port-robust.  For the ultimate in future-protection
paranoia, you could add a static check to ensure that sizeof(off_t) ==
sizeof(int64_t).  I think that's about as close as you can get, and it
doesn't distinguish between long int and long long if both are 64-bit.

> ... I'm still curious to know whether there's a simple way for a gcc *user* to
> distinguish between long and long long when both are 64 bits.  typeof doesn't
> seem to help here.  I guess I'm really after some imaginary extension
> 'rank_of' that lets me do

C?  I don't think so.

C++?  Yes, standard C++.  (You can use C++ as a "better C".  But these days,
that will probably get you scowls from C folks who eschew C++.)

Sincerely,
--Eljay



Re: Distinguishing between long and long long on an LP64 machine?

by Mark Dickinson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Oct 27, 2009 at 12:32 PM, John (Eljay) Love-Jensen
<eljay@...> wrote:
> Hi Mark,
>
>> If I'm using gcc on a machine where both long and long long also have 64 bits,
>> is there any simple C99 (+ gcc extension) code that will allow me to figure
>> out whether this type is ultimately defined as long or long long?
>
> If you are using C++, yes.  If you are using C... I don't think so.

Many thanks for the response, and sorry for the delay in replying.

> For your example, this is how I do it:
>
> off_t my_offset;
> //...
> printf("%lld", (long long)my_offset);

Thanks.  That's more-or-less what I've ended up with, modulo
worrying about Windows/MSVC, and about platforms that
don't have long long.  I just wanted to make sure I wasn't
missing some other obvious solution for silencing these gcc
warnings.

To provide a bit of context, I was working on a portion of the
Python codebase, which mostly tries to be C89 conforming.
C99 features like long long or int64_t are used, but they're
usually enclosed in appropriate preprocessor conditionals,
with some C89 fallback code that's supposed to work
everywhere.  (And catering to MSVC adds another layer of
complexity.)

The code in question (see the _buffered_raw_tell function in
[1] if you want the gory details) was printing expressions of
type off_t using "%zd", leading (naturally) to gcc warnings
on Unix.  To a younger and more foolish me it looked like
a five minute task to fix this.  Now I'm older and wiser!

>> ... I'm still curious to know whether there's a simple way for a gcc *user* to
>> distinguish between long and long long when both are 64 bits.  typeof doesn't
>> seem to help here.  I guess I'm really after some imaginary extension
>> 'rank_of' that lets me do
>
> C?  I don't think so.

Okay, thanks. As far as I can tell from staring at the standards,
in the absence of permitted oddities like paddings bit or trap
representations, it seems that two two's complement signed
integer types of different ranks but the same precision are
completely indistinguishable (with respect to semantics) within
standard C.  With gcc, the warning I get from printf seems to
be the only visible difference.

Mark

[1] http://svn.python.org/view/python/trunk/Modules/_io/bufferedio.c?view=markup