uint16_t和uint32_t之间的差异

时间:2019-07-04 06:25:22

标签: c raspbian bit-shift

在我的代码中,uint16_t和uint32_t之间没有区别。为什么?

我在具有ARMv7(32位)的RasPi上使用Raspbian。

root@zentrale:/src# uname -a
Linux zentrale 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

这是代码:

void main()
{

        uint16_t wert1;
        uint32_t wert2;

        int i;

        wert1=2;
        wert2=2;
        for (i=0; i<33;i++)
        {
                printf("i: %2d\tLShifted wert1: %10u\t",i,wert1 << i);
                printf("RShifted wert1: %10u\t",wert1 >> i);
                printf("LShifted wert2: %10u\t",wert2 << i);
                printf("RShifted wert2: %10u\n",wert2 >> i);
        }
exit(0);
}

这是剥离后的输出:

i:  0   LShifted wert1:          2      RShifted wert1:          2      LShifted wert2:          2      RShifted wert2:          2
i:  1   LShifted wert1:          4      RShifted wert1:          1      LShifted wert2:          4      RShifted wert2:          1
[...]
i: 14   LShifted wert1:      32768      RShifted wert1:          0      LShifted wert2:      32768      RShifted wert2:          0
i: 15   LShifted wert1:      65536      RShifted wert1:          0      LShifted wert2:      65536      RShifted wert2:          0
i: 16   LShifted wert1:     131072      RShifted wert1:          0      LShifted wert2:     131072      RShifted wert2:          0
[...]

我本来希望wert1为16位,而i = 15值则为零,顾名思义,它长16位。

这两个变量没有区别。

我在Raspian中找到了uint16_t最大值的一些参考(请参见https://raspberry-projects.com/pi/programming-in-c/memory/variables

那为什么没有区别?

非常感谢!

2 个答案:

答案 0 :(得分:2)

Both operands of << will undergo integer promotions,即C11 6.3.11p2

  

2在可以使用int或unsigned int的表达式中可以使用以下内容:

     
      
  • 具有整数类型(int或unsigned int除外)的对象或表达式,其整数转换等级小于或等于int和unsigned int的等级。
  •   
  • _Bool,int,signed int或unsigned int类型的位字段。
  •   
     

如果int可以表示原始类型的所有值(受位字段的宽度限制),则该值将转换为int;否则,它将转换为unsigned int

由于您平台上的int是32位宽,所以uint16_t的所有值都可以用int表示。 uint32_t将转换为unsigned int

现在,两者的行为似乎相等,因为 GCC保证了大多数! GCC支持的所有架构上的所有带符号算术均使用2的补码;和additionally GCC does not consider the behaviour << on signed numbers as undefined in the cases where the sign bit is changed

但是,如果移位宽度大于或等于操作数的宽度(在这种情况下为32位),会发生仍然(即使在GCC中也是如此)的情况,所以{{1 }}和<< 32将具有不确定的行为。

除此之外,通常,C标准指出,如果将正号整数左移以使符号位发生变化,则行为是不确定的!当您将<< 33左移太多位时,就会发生这种情况,它将改变uint16_t的移位位。因此,

int

在32位平台上具有未定义的行为,因为最高位已移至(uint16_t)0xFFFF << 16 的符号位,而

int

不会,因为后者将使用无符号算术。与往常一样,编译器可以定义超出标准要求的行为。

答案 1 :(得分:1)

没有区别,因为整数促销

您真的应该阅读有关Implicit type promotion rules主题的精彩文章

假设4个字节int,在进行任何算术运算之前,将uint16_t转换为带符号的int,然后执行该运算。

未定义负数的左移。但是在这种情况下,该数字不能为负。因此,您将获得与uint32_t

相同的输出

您应该键入左移的输出以正确操作。

此外,您正在运行循环,直到i<33。在i==32,您将拥有uint32_t的未定义行为,在i==31中,您将拥有uint16_t的有符号整数的未定义行为

 printf("i: %2d\tLShifted wert1: %10u\t",i,  (uint16_t)(wert1 << i);