浅谈C语言表达式中的整形提升

C语言发明人丹尼斯·里奇与肯·汤普逊关于整型提升(integral promotion)的定义为:
"A character, a short integer, or an integer bit-field, all either signed or not, or an object of enumeration type, may be used in an expression wherever an integer maybe used. If an int can represent all the values of the original type, then the value is converted to int; otherwise the value is converted to unsigned int. This process is called integral promotion."

由上面的定义可归纳出以下两个原则:
1)只要一个表达式中用到了整型值,如类型为char、short int或整型位域(无论是否有符号)的变量,以及枚举类型的对象。
2)如果1)中的变量的原始类型的所有值可以被int完全表示,那么原值被转换为int;否则的话,转为unsigned int。

一个表达式(如四则运算、比较运算等),凡是使用整形的地方,均存在整形提升。下面举个实例演示说明:
#include "stdio.h"
#include "stdint.h"

void main() {
    printf("(uint16_t)0 > -1: %s\n", (uint16_t)0 > -1 ? "true" : "false");
    printf("(uint32_t)0 > -1: %s\n", (uint32_t)0 > -1 ? "true" : "false");
}

[root@HLZ test]# gcc main.c
[root@HLZ test]# ./a.out
(uint16_t)0 > -1: true          (1)
(uint32_t)0 > -1: fasle         (2)

结果(1):对于字节长度小于int类型(如unsigned char、char、short等)的整形,由于该变量的原始类型的所有值可以被int表示,默认会提升为int类型再进行值比较,这种情况的整形提升不会出现任何问题。
结果(2):由于比较符的左值为uint32_t类型,无法被int完全表示,则右值-1也会被提升为uint32_t类型,值变成0xFFFFFFFF后再进行比较,造成难以预知的结果。

综上,对于整形提升,存在以下规律:

1)若有符号类型的整形或小字节长度的无符号类型的整形 提升为 有符号类型的整形,如unsigned char/char/short -> int -> long -> long long,不会引入问题;

2)而 有符号类型的整形 提升为 无符号类型的整形,即int -> unsigned int,且原整形为负值则会引入问题;

3)注意,表达式两侧的整形类型会同步提升;符号位占位的单个整形数值会根据默认规则提升。

那么,如何尽可能地避免 int -> unsigned int的整形提升呢?方法是有的,显式地进行强制类型转换。
* 对于单个整形数值,如在定义常量宏,特别是负值常量宏时加上类型,如下:
  #define INT32_MIN   (int32_t)(-2147483648)

* 对于表达式,如进行两个整形数值比较或运算,且存在负值整形情况,为了避免整形提升为uint32_t,可考虑使用更大字节长度的int64_t类型化。在软件工程中,负整形结果多为异常情况,应考虑提前判断规避。

最后,再重复一遍重点:如果表达式中存在负值整形,务必提高警惕。通过在表达式两侧用合适的有符号类型(甚至更大字节长度的有符号类型)强转,确保原负值不会被整形提升为一个很大的无符号正整数的情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值