【问题标题】:Right Shifting Unsigned Integers in C Issue: Vacated Bits Not 0 When Shifting ~0?C问题中的无符号整数右移:移位~0时空位不为0?
【发布时间】:2018-01-07 04:36:54
【问题描述】:

据我了解,当将 C 中的无符号整数右移多个位置时,左侧的空位将被零填充。

但是,我一直在尝试右移 ~0(即 1111...1111),但完全没有成功。尝试将其右移任意数量的位置都会产生相同的值,除非我在移位之前将整数存储在变量中:

#include <stdio.h>

int main() {

    // Using an expression:
    printf("%u \n", ~0);
    printf("%u \n", ~0 >> 2);
    unsigned int temp = ~0;
    // Using a variable to store the value before shift:
    printf("%u \n", temp);
    printf("%u \n", temp >> 2);

    return 0;

}

输出:

4294967295                                                                                   
4294967295                                                                               
4294967295                                                                                  
1073741823 

以任何一种方式执行左移 ~0 都非常好。我不确定这里发生了什么。

【问题讨论】:

  • printf("%u \n", ~0); 是 ub,0int 文字。
  • ~0 的类型为 int。使用%u 格式打印它会产生未定义的行为。

标签: c bit bit-shift kernighan-and-ritchie


【解决方案1】:

表达式0 的类型是int,而不是unsigned int。因此,~0int,其值为 0xffffffff(假设是 32 位 ints,看起来像您拥有的那样)。在大多数系统上,这意味着-1,右移一个有符号整数将符号扩展(如果它开始为负,则保持为负),再次给出0xffffffff

当您使用%u 打印它时,printf 函数将这个带有值-1 的签名int 读取为unsigned int,并打印0xffffffffunsigned int 的含义。

请注意,所有这些都是大多数系统中大多数时间发生的事情。这有多个未定义或实现定义的行为实例(负ints 的位模式,右移负ints 的作用,以及%u 格式说明符在您传入int 时的含义unsigned int)。

【讨论】:

    【解决方案2】:
    ~0U >> 2
    

    这将确保它是未签名的。否则你已经签署了操作。

    整型文字总是int 类型(签名int)。现在,当您左移时,它是符号扩展的。

    %u 需要无符号整数。您已将签名的 int 传递给它。这是未定义的行为。

    【讨论】:

      【解决方案3】:

      以下提议的代码更正了 OPs 代码并解决了问题的 cmets,包括删除未定义的行为。

      #include <stdio.h>
      
      int main( void )
      {
          // Using an expression:
          printf("%u \n", ~0U);
          printf("%u \n", ~0U >> 2);
          unsigned int temp = ~0U;
          // Using a variable to store the value before shift:
          printf("%u \n", temp);
          printf("%u \n", temp >> 2);
      
          return 0;
      }
      

      输出是:

      4294967295 
      1073741823 
      4294967295 
      1073741823 
      

      【讨论】:

        猜你喜欢
        • 2020-11-23
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-05
        • 1970-01-01
        相关资源
        最近更新 更多