Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which initializer is appropriate for an int64_t?

Tags:

c

gcc

int64

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)?

like image 965
Alex Reynolds Avatar asked Nov 07 '12 17:11

Alex Reynolds


People also ask

What is int64_t?

A long on some systems is 32 bits (same as an integer), the int64_t is defined as a 64 bit integer on all systems (otherwise known as a long long). Portability may be affected using long, but using int64_t looks like it was created to increase portability.

Is int64_t same as long?

In a 64-bit compile, int64_t is long int , not a long long int (obviously).


2 Answers

int64_t method_one   = 0;

...is perfectly reasonable. C99 (see e.g. 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:

  • the 0 has type int (§6.4.4.1 para.5);
  • the type of the expression is int64_t (§6.5.16 para.3);
  • the type of the right-hand side will be converted to the type of the expression (§6.5.16.1 para.2);
  • this conversion will not change the value (§6.3.1.3 para.1).

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.)

like image 100
Matthew Slattery Avatar answered Oct 24 '22 06:10

Matthew Slattery


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.

like image 22
md5 Avatar answered Oct 24 '22 05:10

md5