I like to initialize my variables to some "dummy" value and have started to use int64_t
and uint64_t
. So far, it looks like there are at least three ways I could initialize an int64_t
to a particular value (and with slight changes for the unsigned equivalent):
int64_t method_one = 0;
int64_t method_two = 0LL;
int64_t method_three = INT64_C(0);
I use GCC and target OS X and Linux. I'd like to pick a method that aims for ease of portability and clarity — but correctness, above all. Am I overthinking this, or is there a "best" or "most recommended" approach for initializing this variable type, for any particular value I throw at it (which is within its bounds, of course)?
int64_t method_one = 0;
...is perfectly reasonable. C99 (see eg draft here ; yes, I know it's not the most recent standard any more, but it's the one that introduced the int<N>_t
types) says that:
0
has type int
(§6.4.4.1 para.5); int64_t
(§6.5.16 para.3); So there's nothing wrong with that at all, and the lack of additional clutter makes it the most readable of the options when initialising to 0 or anything else in the range of an int
.
int64_t method_two = 0LL;
int64_t
is not guaranteed to be the same as long long
; however, this should in fact work portably for any signed 64-bit value as well (and similarly ULL
for unsigned 64-bit values): long long
(and unsigned long long
) should be at least 64 bits in a C99-compliant implementation (§5.2.4.2.1), so LL
(and ULL
) should always be safe for initialising 64-bit values.
int64_t method_three = INT64_C(0);
This is arguably a better option for values which may be outside the range of an int
, as it expresses the intent more clearly: INT64_C(n)
will expand to something appropriate for any n
in (at least) a 64-bit range (see §7.18 in general, and particularly §7.8.4.1).
In practice, I might well use any of the above, depending on context. For example:
uint64_t counter = 0;
(Why add unnecessary clutter?)
uint64_t some_bit = 1ULL << 40;
( 1 << 40
simply won't work unless int
is unusually wide; and UINT64_C(1) << 40
seems less readable to me here.)
uint64_t some_mask = UINT64_C(0xFF00FF00FF00FF00);
(In this case, explicitly calling out the value as a 64-bit constant seems more readable to me than writing 0xFF00FF00FF00FF00ULL
.)
Personnally, I would use the third, which is the most portable way to achieve this.
#include <stdint.h>
int64_t method_three = INT64_C(0);
uint64_t method_three = UINT64_C(0);
Anyway, I don't think it's a very important thing.
According to the ANSI C standard, the suffix for a long long int
and unsigned long long int
is LL
and ULL
respectively:
octal or hexadecimal suffixed by ll or LL long long int, unsigned long long int decimal, octal, or hexadecimal suffixed by both u or U, and ll or LL unsigned long long int
If you know that int64_t
is defined as:
typedef signed long long int int64_t
Then method two is most definitely the correct one:
int64_t method_two = 0LL;
uint64_t method_two = 0ULL;
Edit :
Keeping in mind the portability issues, and the fact that it's not guaranteed to be defined as long long
, then it would be better to use the third method:
INT64_C()
UINT64_C()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.