【问题标题】:left shift operator (<<) in c programing languagec语言中的左移运算符(<<)
【发布时间】:2022-11-03 01:42:24
【问题描述】:

我正在学习使用 C 进行位操作。在编写将二进制转换为十进制的程序时遇到了一个问题,尤其是在程序的 for 循环中。以下是我的代码:

unsigned int binary_to_uint(const char *b)
{
    unsigned int result = 0;
    int i, len;
    if (!b)
        return (0);
    len = strlen(b);
    for (i = 0; i < len; i++)
    {
        if (b[i] == '1')
        {
            result += 2 << (i-1); /*where my issue is*/
        }
        else if (b[i] == '0')
            continue;
        else
            return (0);
    }
    return (9);
}

我尝试调试,我意识到我的问题源于如果陈述

因此,我对如果* 陈述:

int main() {
    // Write C code here
    int i = 0;
    printf("result of 2 << (%d - 1): %d\n", 2 << (i - 1));
    printf("result of 2 << (0 - 1): %d", 2 << (0 - 1));

    return 0;
}

在第一个 printf 中,显示2 << (0 - 1) 的结果:0在控制台中,而 在第二个 printf 中,显示2 << (0 - 1) 的结果:1在控制台中。 我的期望是两个 printf 应该显示完全相同的东西,即2 << -1 是 1,然而事实并非如此。有人可以帮我了解发生了什么。为什么使用变量 i 将移位运算符的结果更改为 0?

【问题讨论】:

  • printf("result of 2 &lt;&lt; (%d - 1): %d\n", 2 &lt;&lt; (i - 1)); 有两个格式说明符,但只有一个参数。

标签: c bit-manipulation


【解决方案1】:

&lt;&lt;&gt;&gt; 运算符的右侧操作数必须为非负数。对此操作数使用负值会触发undefined behavior。因此,您不能使用负值向相反方向移动。

这在C standard 的第 6.5.7p3 节中有详细说明:

对每个操作数执行整数提升。类型 结果是提升的左操作数的结果。如果值 右操作数为负数或大于等于宽度 在提升的左操作数中,行为未定义。

在您的特定情况下,未定义的行为表现为将 i-10-1 用于正确的操作数之间的不同结果。

不是将2 移动i-1 位置,而是将1 移动i 位置:

result += 1 << i; 

【讨论】:

    【解决方案2】:

    如果b[i] 等于1,那么您需要使用len - i - 1 移动1u

        if (b[i] == '1')
        {
            result += 1u << len - i - 1;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多