gpt4 book ai didi

c - 按位 c - 在 for 循环内不同的结果(不知道如何放置更好)

转载 作者:太空宇宙 更新时间:2023-11-04 04:59:46 27 4
gpt4 key购买 nike

int bitcheck(int test){
int result = 0, unit = 0, i;
for (i = 0; i < 8; i++){
unit = test >> i & 1;
result |= unit << (8 - i - 1) + result;
}
return result;
}

假设测试 = 77 (0100 1101)

当 i = 2 时,单位将等于 1,结果将(在“结果 |=..”之前)等于 128。所以 1 << 133(在计算“结果 | 结果”之前)是 0010 0000 ? (我打印了每一步),但如果我自己做 1<<133 结果是 0000 0000?

我知道为什么 1<<133 的结果是 0000 0000,但为什么在 for 循环中不一样?

test is: 01001101

unit when i is 0: 00000001
00000001<<00000111 = 10000000
result when i is 0: 10000000

unit when i is 1: 00000000
00000000<<10000110 = 00000000
result when i is 1: 10000000

unit when i is 2: 00000001
00000001<<10000101 = 00100000
result when i is 2: 10100000

unit when i is 3: 00000001
00000001<<10100100 = 00010000
result when i is 3: 10110000

unit when i is 4: 00000000
00000000<<10110011 = 00000000
result when i is 4: 10110000

unit when i is 5: 00000000
00000000<<10110010 = 00000000
result when i is 5: 10110000

unit when i is 6: 00000001
00000001<<10110001 = 00000000
result when i is 6: 10110000

unit when i is 7: 00000000
00000000<<10110000 = 00000000
result when i is 7: 10110000


return result: 10110000

最佳答案

正如其他人所指出的,这是 undefined behavior ,这意味着如果您只需要遵循 C 标准,那么理论上任何事情都可能发生。

不过,我认为这对您的问题有点无益,因为您会想知道为什么对相同的两个数字进行相同的操作会产生不同的结果。毕竟,虽然 C 标准没有指定结果是什么,但 CPU 本身确实遵循其自己的位移指令工作方式规范,并且不太可能涉及生成随机结果。

您看到的差异很可能是由于 CPU 的移位实现与编译器在预计算编译时已知结果时使用的实现之间的差异。例如考虑这个简单的例子:

$ cat shift.c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
int main(int argc, char ** argv)
{
uint32_t a = atoi(argv[1]), b = atoi(argv[2]), c, d;
c = a << b;
d = 1u << 133u;
printf("%08x << %08x = %08x\n",a,b,c);
printf("%08x << %08x = %08x\n",1,133,d);
return 0;
}
$ gcc -o shift{,.c}
shift.c: In function ‘main’:
shift.c:9:2: warning: left shift count >= width of type
$ ./shift 1 133
00000001 << 00000085 = 00000020
00000001 << 00000085 = 00000000

这是在 Intel Core2 Duo cpu 上运行的。看似相同的操作在这里执行了两次却得到了不同的结果。但是这两个操作实际上并不等同。第一个涉及编译器不知道其值的数字,因此它们被简单地编译成一条 sall x86 指令。本说明书only uses the lowest 5 bits of the count . 133 (0x85) 的最低 5 位是 5,因此实际执行的位移是 1 << 5 = 32 (0x20),这与输出匹配。所以这是有道理的。

但是另一条线发生了什么?这里编译器知道两个操作数是什么,所以它可以预先计算结果并存储它。没有生成 sall 指令。 gcc 的位移位实现(仅当结果可以在编译时计算时才起作用)处理太大计数的方式与 sall 不同。在这种情况下,有效地使用了整个计数,并且所有位都被移走了。

总结一下:

  1. 非法计数导致未定义的行为
  2. 在编译时已知的值的未定义移位会暴露编译器对未定义操作的实现。
  3. 在编译时已知的值的未定义移位会暴露 CPU 对未定义操作的实现。
  4. 第 2 点和第 3 点是您看到位移结果不一致的原因。

关于c - 按位 c - 在 for 循环内不同的结果(不知道如何放置更好),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31224205/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com