我真的不知道为什么位移位在一种情况下有效,但在另一种情况下不起作用

Sh1*_*h1r 3 c bit-shift

所以我正在做一些位移,我遇到了以下问题,我将非常感激得到答案:

作为参数,我可以传递 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;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我像这样替换位移部分,则分母给出与分子相同的输出:

unsigned char numerator = atoi(argv[i]);
        numerator = (numerator >> 4) << 4;

unsigned char denominator = atoi(argv[i]);
        denominator = (denominator << 4) >> 4;
Run Code Online (Sandbox Code Playgroud)

示例输入为:

./test 1
./test 16
Run Code Online (Sandbox Code Playgroud)

给出的输出:

0/1
16/16
Run Code Online (Sandbox Code Playgroud)

预期输出:

0/1
16/0
Run Code Online (Sandbox Code Playgroud)

预先感谢您的任何帮助。

use*_*109 5

当在 C 中计算算术表达式时,任何小于 的整数类型都会在执行计算之前int提升为。int


所以这段代码:

unsigned char denominator = atoi(argv[i]);
denominator = (denominator << 4);
denominator = (denominator >> 4);
Run Code Online (Sandbox Code Playgroud)

结果如下序列(每个框代表 4 位,框中的文本是十六进制数字):

在此输入图像描述

请注意,赋值denominator = (denominator << 4);会强制编译器将值转换回unsigned char. 然后在下一行代码中,编译器需要将其提升unsigned charint.


但是这段代码:

unsigned char denominator = atoi(argv[i]);
denominator = (denominator << 4) >> 4;
Run Code Online (Sandbox Code Playgroud)

跳过转换回unsigned char以及第二次升级到int。所以顺序是:

在此输入图像描述

请注意,最终值与原始值相同,因为移位是使用 32 位执行的,并且没有从 32 位值的左侧移出任何内容。


分子则不存在同样的问题。因为分子先右移,所以右边的位会丢失。晋升至int对结果没有影响。这是分子的序列:

在此输入图像描述