ARM CMSIS-NN库乘2的幂为何用移位后相乘而非直接移位写法
核心原因:规避有符号整数左移的未定义行为
- C语言标准明确规定,有符号整数左移操作如果数值为负,或者移位后的结果超出该类型可表示的范围,属于未定义行为(UB)。你给出的示例中
val是int32_t带符号类型,如果val为负,直接写val << shift的行为完全不受标准约束,编译器可能生成不符合预期的代码,甚至直接优化掉整段逻辑。 - 乘法写法的行为是完全明确定义的:
1 << shift在CMSIS-NN的业务逻辑中会保证shift取值在0~30之间,避免1移位后溢出,得到的是一个正的int32_t整数,有符号数乘正整数的结果规则完全符合补码运算预期,不存在未定义行为。 - 两种写法的实际运行效率没有区别。现代编译器只要开启O1及以上优化,会自动把乘以2的幂的操作转换为等价的移位指令,完全不会有额外的性能损耗,和直接写移位的运行效率完全一致。
为什么该库其他地方会用直接移位
其他使用直接移位的场景,要么val是无符号整数类型(无符号整数左移的行为是标准明确定义的,溢出也会按模2^n规则处理),要么业务逻辑已经100%保证val是非负的有符号数,此时左移的行为是确定的,所以可以直接写移位。
内容的提问来源于stack exchange,提问作者Fabian
相关产品推荐
相关产品推荐

