Why do many of the online judges advise "do not use the %lld
specifier to read or write 64-bit integers in С++"?
Is it preferred to use the cin
, cout
streams or the %I64d
specifier?
Why do many of the online judges advise "do not use the %lld
specifier to read or write 64-bit integers in С++"?
Is it preferred to use the cin
, cout
streams or the %I64d
specifier?
I believe the answer is related to %lld
means long long decimal
, which isn't guaranteed to be 64-bit. It could be, for example 128 bit on some systems. (Although if the variable is long long
rather than, say, uint64_t
, then I expect %lld
is the right thing to use - or it would go wrong the other way around)
Unfortunately, the design of printf
and scanf
and their siblings is such that the compiler implementation and the format must match.
Obviously, cout
and cin
are safe in the sense that the compiler will chose the right output and input translation in itself.
It may also have something to do with what compiler(s) the "online judges" use - I think Microsoft compilers at some point supported 64-bit integers, but not long long
, and thus didn't have %lld
, but did have %l64d
.
The <<
and >>
operators on cin
and cout
have versions for every integer and floating-point type. If you use cin
and cout
, you just do cin >> integer_variable
or cout << integer_variable
and you're done, cin
and cout
will figure out what to do.
If you use some sort of printf()
, then you must be very careful in what you pass to it. If you pass to it an int
, you must also pass its type specifier "%d"
, for unsigned int
it's "%u"
, for long
it's "%ld"
, for unsigned long long
it's "%llu"
, for size_t
it's "%zu"
and so on. If you pass a type specifier that doesn't match the type of your integer, you'll invoke undefined behavior. As a result, your program may print wrong numbers or corrupt itself or hang or crash or misbehave in some other mysterious way.
Now, the C++11 language standard (and C99) has at least one integer type that's 64-bit or longer, long long
(and its unsigned counterpart, unsigned long long
). If you use it, you must be aware that it can be longer than 64 bits. If your compiler provides another type, __int64
or int64_t
(plus the unsigned version of the same), that's exactly 64-bit, you shouldn't mix and match their type specifiers as it's often mistakenly done. You should still use "%lld"
and "%llu"
for long long
and unsigned long long
and whatever's appropriate for __int64
(perhaps, "%I64d"
) and for int64_t
(PRId64
macro).
Basically, you should either avoid using printf()-like
functions or be very careful with them.
Ans to 1:
Because in their background they use compiler. GNU
supports %l64d
, and MS
supports %lld
and %l64d
.
Ans to 2:
Yes, it is preferred to use the cin
, cout
. Because internally they take decision by their own.
© 2022 - 2024 — McMap. All rights reserved.
long long
is 64 bit long, for example? – Indigestibleprintf
is not type safe. If user passes some other type then it gives you Undefined behavior. While withcout
the compiler appropriately chooses an valid overload version depending on the type or it returns an error, there is no Undefined behavior. – Mineral%l64d
is the format specification which tells the compiler that the number passed as argument will be64
bit long. But it is not necessary that the typelong long
used to store these numbers are actually64
bit on every environment. Any mis-match in format specification and actual data being passed toprintf
technically gives you an Undefined behavior. So this type unsafe behavior might bite you badly. – Mineral