%llu on 64bit architecture

M

Max Laier

What should a compiler on a 64bit platform do with the following:

unit64_t x=1234567;
printf("%llu", x);

On 32Bit unit64_t is usually a macro for "unsigned long long" so above
example is perfectly right.
On 64Bit unit64_t is usually a macro for "unsigned long" so above code might
cause a warning.

Of course you can use PRIu64 to avoid that, but many docs on printf tell
you:

"The optional character sequence ll, specifying that a following d, i, o, u,
x, or X conversion corresponds to a **quad** int or unsigned **quad** int
argument, or that a following n conversion corresponds to a pointer to a
quad int argument. The use of q has been deprecated as conversion
character."

A quad, however, is 64bit on every platform and hence %llu should print
uint64_t without a warning.

What do you think? Is this right or wrong?
What is the real meaning of %llu:
- print a "long long" variable?
- or print a 64bit varibale?

Regards
Max
 
D

dbtid

Max Laier wrote:

[snip]
On 32Bit unit64_t is usually a macro for "unsigned long long" so above
example is perfectly right.
On 64Bit unit64_t is usually a macro for "unsigned long" so above code might
cause a warning.

Those are probably not macros. They are probably typedefs.

[snip]
 
R

Robert W Hand

"The optional character sequence ll, specifying that a following d, i, o, u,
x, or X conversion corresponds to a **quad** int or unsigned **quad** int
argument, or that a following n conversion corresponds to a pointer to a
quad int argument. The use of q has been deprecated as conversion
character."

A quad, however, is 64bit on every platform and hence %llu should print
uint64_t without a warning.

According to C99, the ll length modifier is used with unsigned long
long int or long long int depending on the conversion specifier. If
the argument is not of the correct type for the conversion
specification, then the behavior is undefined. From the documentation
that you provided, it seems that they have provided an extension for
you.

Best wishes,

Bob
 
C

Chris Torek

What should a compiler on a 64bit platform do with the following:

unit64_t x=1234567;
printf("%llu", x);

It should produce a diagnostic, because "unit64_t" is not syntactically
valid. :)

Obviously you meant "uint64_t", and meant to imply that some header
file was included first so that uint64_t is a typedef for some other
type. Then the question is: what other type? If uint64_t is an
alias for "unsigned long long", the above is valid. If it is an
alias for some other type, the call probably violates various
"shall"s that are outside "Constraints" section, and hence is not
only wrong but also does not require a diagnostic.
On 32Bit unit64_t is usually a macro for "unsigned long long" so above
example is perfectly right.
On 64Bit unit64_t is usually a macro for "unsigned long" so above code might
cause a warning.

Of course you can use PRIu64 to avoid that, but many docs on printf tell
you:

"The optional character sequence ll, specifying that a following d, i, o, u,
x, or X conversion corresponds to a **quad** int or unsigned **quad** int
argument, or that a following n conversion corresponds to a pointer to a
quad int argument. The use of q has been deprecated as conversion
character."

A quad, however, is 64bit on every platform and hence %llu should print
uint64_t without a warning.

The problem here is that C does not have a type called "quad".

C89 does not even have the "long long" type, and does not guarantee
the existence of any 64-bit type.

Some systems, including the BSD Unix-like systems, needed a 64-bit
type long before the C99 standard existed. So, in 1991, we[%]
charged on ahead and used GCC's 64-bit "long long" extension, gave
it a shorter name we invented and called "quad", and added the
"%qd" format to printf. We put this in the manual pages and noted
that it was non-ANSI. If you are using a BSD-based system, this
is likely where the above came from. If you are using a system
that cloned ideas from our BSD-based systems, it is probably still
where the above came from.

[%Footnote: primarily Keith Bostic and myself.]

Today, you are using our 1991-era name and expecting it to mean
something specific in C99. Alas, we are not entirely lucky --
while C99 added "long long", they did not call it "quad" nor use
"%qd" as a printf() format.
What do you think? Is this right or wrong?
What is the real meaning of %llu:
- print a "long long" variable?

According to C99, this is what it means.

If you are using an earlier version of C, it has *no* defined
meaning (which is how we were able to run off with it and do
something we considered useful -- but if you use our meaning, you
run the risk of having any OTHER implementation run off with it
and do something different).
- or print a 64bit varibale?

On the systems on which we did our thing, these were the same. On
C99 systems, these are not necessarily the same. *You* must choose:
whether to use C99, or C89-with-our-extensions, or C89-with-someone-
else's-extensions, or whatever it is you like.
 
D

Dan Pop

In said:
What should a compiler on a 64bit platform do with the following:

uint64_t x=1234567;
printf("%llu", x);

In the general case, it is undefined behaviour, because uint64_t need not
be a typedef for usigned long long.

The correct versions are:

uint64_t x = 1234567;
printf("%" PRIu64, x);

or

unsigned long long x = 1234567;
printf("%llu", x);

Note that this issue has absolutely nothing to do with the platform's
size. uint64_t and PRIu64 need not be defined by the implementation
(unless it provides a "native" type with the required properties).

Dan
 

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,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top