所以我正在做一些位移,我遇到了以下问题,如果能得到答案,我将非常感激:
作为参数,我可以传递 1 个字节的大小。
前 4 位代表一个分子。 最后4位代表分母。
以下代码有效并给出正确的输出:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char** argv)
{
for(int i = 1; i < argc; i++)
{
unsigned char numerator = atoi(argv[i]);
numerator = (numerator >> 4);
numerator = (numerator << 4);
unsigned char denominator = atoi(argv[i]);
denominator = (denominator << 4);
denominator = (denominator >> 4);
printf("%d/%d\n", numerator, denominator);
}
return 0;
}
但是如果我像这样替换位移部分,分母给出与分子相同的输出:
unsigned char numerator = atoi(argv[i]);
numerator = (numerator >> 4) << 4;
unsigned char denominator = atoi(argv[i]);
denominator = (denominator << 4) >> 4;
示例输入为:
./test 1
./test 16
给出的输出:
0/1
16/16
预期输出:
0/1
16/0
提前感谢任何形式的帮助。
最佳答案
在 C 中计算算术表达式时,任何小于 int
的整数类型晋升为int
在执行计算之前。
所以这段代码:
unsigned char denominator = atoi(argv[i]);
denominator = (denominator << 4);
denominator = (denominator >> 4);
结果如下(每个框代表4位,框内文字为十六进制数字):
注意赋值 denominator = (denominator << 4);
强制编译器将值转换回 unsigned char
.然后在下一行代码中,编译器需要提升 unsigned char
返回 int
.
但是这段代码:
unsigned char denominator = atoi(argv[i]);
denominator = (denominator << 4) >> 4;
跳过转换回unsigned char
第二次晋升为int
.所以顺序是:
请注意,最终值与原始值相同,因为移位是使用 32 位执行的,并且没有从 32 位值的左侧移出任何内容。
分子没有同样的问题。因为分子先右移,所以右边的位会丢失。促销至int
对结果没有影响。这是分子的顺序:
关于c - 我真的不知道为什么移位在一种情况下有效,但在另一种情况下无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61433792/