[踩坑]整型提升

C was designed to implicitly and silently change the integer types of the operands used in expressions. ……These rules are often not even known by the average C programmer and therefore causing all manner of very subtle bugs.

——stackoverflow/implicit-type-promotion-rules

之所以踩到这个坑里,是在将C/C++代码改写为NEON时,忽略了整型提升,将原本应该提升为int的结果用short来保存了,导致结果错误。

从一个简单的例子开始吧:

int main()
{
	short s1 = 32767;
	short s2 = ((s1 + 5) >> 2);
	short s3 = ((short)(s1 + 5) >> 2);
	short s4 = ((unsigned short)(s1 + 5) >> 2);
	return 0;
}

最终s2的结果为8193,s3为-8191,s4为8193。
这里,在计算s2时,便发生了整型提升:s1+5得到32772,再右移2位便得到8193。而计算s3时,s1+5所得的32772(0x8004)先转换为short型即-32764(0x8004),再进行算数右移,高位补1,便得到-8191。计算s4时,与s3的不同之处是将0x8004转换为了unsigned short型,因此算数右移时高位补0,得到的也就是8193了。

P.S. 复习一下C/C++的移位运算:左移是逻辑移动(从末端移掉的位将被舍弃,包括符号位);右移是算数移动,对于无符号数字,因移位运算而空出的位上将用零填充。 对于有符号数字,符号位用于填充空出的位。

文章开头引用的stackoverflow上的文章对整型提升做了比较全面的介绍,还有usual arithmetic conversion,可参考。

Formally, the rule says (C11 6.3.1.1):

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.

This means that all small integer types, no matter signedness, get implicitly converted to (signed) int when used in most expressions.

This text is often misunderstood as: “all small, signed integer types are converted to signed int and all small, unsigned integer types are converted to unsigned int”. This is incorrect. The unsigned part here only means that if we have for example an unsigned short operand, and int happens to have the same size as short on the given system, then the unsigned short operand is converted to unsigned int. As in, nothing of note really happens. But in case short is a smaller type than int, it is always converted to (signed) int, regardless of it the short was signed or unsigned!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值