[英]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==32
, uint32_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.