哪个初始化程序适用于int64_t?

我喜欢将我的变量初始化为一些“虚拟”值,并开始使用int64_tuint64_t 。 到目前为止,看起来至少有三种方法可以将int64_t初始化为特定值(并且对于无符号的等价物稍有更改):

 int64_t method_one = 0; int64_t method_two = 0LL; int64_t method_three = INT64_C(0); 

我使用GCC并针对OS X和Linux。 我想选择一种旨在简化便携性和清晰度的方法 – 但最重要的是正确性。 我是否过度思考这个,或者是否有一个“最佳”或“最推荐”的方法来初始化这个变量类型,对于我抛出的任何特定值(当然,它在其范围内)?

 int64_t method_one = 0; 

……完全合情合理。 C99(参见例如这里的草案;是的,我知道它不再是最新的标准了,但它是引入int_t类型的那个)说:

  • 0类型为int (§6.4.4.1para.5);
  • 表达式的类型是int64_t (§6.5.16第3段);
  • 右侧的类型将转换为表达式的类型(§6.5.16.1para.2);
  • 此转换不会改变该值(§6.3.1.3第1段)。

因此,根本没有任何问题,并且当初始化为0或int范围内的任何其他内容时,缺少额外的混乱使其成为最可读的选项。

 int64_t method_two = 0LL; 

int64_t不保证与long long相同; 但是,实际上这对于任何带符号的64位值都是可移植的(对于无符号的64位值也是类似的ULL ):在符合C99的实现中, long long (和unsigned long long )应该至少为64位( §5.2.4.2.1),因此LL (和ULL )应始终安全地初始化64位值。

 int64_t method_three = INT64_C(0); 

对于可能超出int范围的值,这可以说是更好的选择,因为它更清楚地表达了意图: INT64_C(n)将扩展到适合于(至少)64位范围内的任何n值(参见§7.18一般,特别是§7.8.4.1)。


在实践中,我可能会使用上述任何一种,具体取决于具体情况。 例如:

 uint64_t counter = 0; 

(为什么要添加不必要的混乱?)

 uint64_t some_bit = 1ULL << 40; 

1 << 40根本不起作用,除非intexception宽;而UINT64_C(1) << 40在这里似乎不太可读。)

 uint64_t some_mask = UINT64_C(0xFF00FF00FF00FF00); 

(在这种情况下,显式地将值作为64位常量调用似乎比写入0xFF00FF00FF00FF00ULL 更具可读性。)

个人而言,我会使用第三种,这是实现这一目标的最便携方式。

 #include  int64_t method_three = INT64_C(0); uint64_t method_three = UINT64_C(0); 

无论如何,我认为这不是一件非常重要的事情。

根据ANSI C标准, long long intunsigned long long int的后缀分别为LLULL

八进制或hex,后缀为ll或LL long long int,unsigned long long int decimal,octal或hexadecimal,后缀为u或U,以及ll或LL unsigned long long int

如果你知道int64_t被定义为:

 typedef signed long long int int64_t 

方法二绝对是正确的方法:

 int64_t method_two = 0LL; uint64_t method_two = 0ULL; 

编辑

牢记可移植性问题,以及不能保证long long定义的事实,那么使用第三种方法会更好:

 INT64_C() UINT64_C()