繁体   English   中英

uint16_t和uint32_t之间的差异

[英]Diff between uint16_t and uint32_t

在我的代码中,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

那么为什么没有区别呢?

非常感谢!

两个操作数<<将进行整数提升 ,即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的补码; 另外GCC不考虑行为<<上为未定义在符号位改变的情况下签署的数字

但是,如果移位宽度大于或等于操作数的宽度(在本例中为32位),则仍然未定义(即使在GCC中)会发生什么,因此<< 32<< 33将具有未定义的行为。

除此之外,一般来说,C标准表示如果左移位正有符号整数,则行为未定义,以使符号位发生变化! 当你将uint16_t向左移动这么多位以改变int的移位时会发生这种情况。 因此,

(uint16_t)0xFFFF << 16

在32位平台上有未定义的行为,因为最高位被移位到int的符号位,而

(uint32_t)0xFFFF << 16

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

由于Integer Promotions没有区别

你应该真正阅读关于主题隐式类型促销规则的这篇优秀文章

假设4字节int ,在任何算术运算之前, uint16_t被转换为signed int ,然后执行该操作。

左数字的负数未定义。 但在这种情况下,这个数字不能是负数。 因此,您将获得与uint32_t相同的输出

您应该对左移的输出进行类型转换以便正确操作。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM