在C中声明64位变量

Dav*_*ong 32 c bit-shift

我有个问题.

uint64_t var = 1; // this is 000000...00001 right?
Run Code Online (Sandbox Code Playgroud)

在我的代码中,这有效:

var ^ (1 << 43)
Run Code Online (Sandbox Code Playgroud)

但它怎么知道1应该是64位?我不应该写这个吗?

var ^ ( (uint64_t) 1 << 43 )
Run Code Online (Sandbox Code Playgroud)

Mat*_*lia 34

正如你所想的那样,1是一个普通的符号int(在你的平台上可能在2的补码算法中是32位宽),因此是43,所以任何机会都会1<<43导致溢出:事实上,如果两个参数都是类型int操作符规则要求结果int也是如此.

仍然,在C签名整数溢出是未定义的行为,因此在原则上任何事情都可能发生.在你的情况下,编译器可能会发出代码来在64位寄存器中执行该移位,所以幸运的是它似乎可行; 要获得保证正确的结果,您应该使用您编写的第二种形式,或者,替代地,使用后缀指定1unsigned long long文字ull(unsigned long long保证至少为 64位).

var ^ ( 1ULL << 43 )
Run Code Online (Sandbox Code Playgroud)


chu*_*ica 11

我推荐OP的方法,抛出常数 ( (uint64_t) 1 << 43 )

对于OP的小例子,下面的2 可能会执行相同的操作.

uint64_t var = 1; 
// OP solution)
var ^ ( (uint64_t) 1 << 43 )
// Others suggested answer
var ^ ( 1ULL << 43 )        
Run Code Online (Sandbox Code Playgroud)

以上结果具有相同的值,但是类型不同.潜在的差异在于C中存在两种类型:uint64_t以及unsigned long long随后可能存在的类型.

uint64_t具有0到2 64 -1 的精确范围.
unsigned long long范围从0到至少 2 64 -1.

如果unsigned long long永远是64位的,因为它似乎是在许多机器有天,有没有问题,但让我们展望未来,并说这个码的机器,其中上已运行unsigned long long了16个字节(0到至少 2 128 -1).

下面的一个人为设想的例子:a的第一个结果^uint64_t,当乘以3时,产品仍将是uint64_t,执行模2 64,如果发生溢出,则结果被分配给d1.在下一种情况下,结果^是a unsigned long long,当乘以3时,乘积可能大于2 64,然后将其分配给d2.所以d1,d2有一个不同的答案.

double d1, d2;
d1 = 3*(var ^ ( (uint64_t) 1 << 43 ));
d2 = 3*(var ^ ( 1ULL << 43 ));
Run Code Online (Sandbox Code Playgroud)

如果想与之合作unit64_t,请保持一致.不要假设unit64_tunsigned long long是一样的.如果答案是好的,那就好了unsigned long long.但根据我的经验,如果一个人开始使用固定大小的类型uint64_t,那么就不希望变体大小类型弄乱计算.