我有个问题.
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位寄存器中执行该移位,所以幸运的是它似乎可行; 要获得保证正确的结果,您应该使用您编写的第二种形式,或者,替代地,使用后缀指定1为unsigned 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_t和unsigned long long是一样的.如果答案是好的,那就好了unsigned long long.但根据我的经验,如果一个人开始使用固定大小的类型uint64_t,那么就不希望变体大小类型弄乱计算.