算数类型之间的转换规则
bool
类型的转换
bool
类型 --> 非bool
类型,false
表示0
,true
表示1
- 非
bool
类型 -->bool
类型,0
表示false
,其它表示true
整数之间的转换(不包括 bool
)
整数 --> 整数
- 如果后者可以表示前者,直接表示即可
- 否则,如果后者是无符号的类型,后者的值域为
[0, N)
,前者将不断加 或 减N
,直到结果位于后者的值域中 - 否则,如果后者是有符号的类型,则是由编译器实现定义
浮点数和整数之间的转换(不包括 bool
)
浮点数 --> 整数
- 首先,忽略前者的小数部分
- 如果忽略后的值可以由后者表示,直接表示即可
- 如果忽略后的值超出了后者所能表示的范围,则是未定义的行为
整数 --> 浮点数
- 如果前者可以由后者精确表示,直接表示即可
- 如果前者可以由后者表示,但不能精确表示,结果会丧失精度
- 如果前者超出了后者所能表示的范围,则是未定义的行为
浮点数之间的转换
浮点数 --> 浮点数
- 如果前者可以由后者精确表示,直接表示即可
- 如果前者可以由后者表示,但不能精确表示,结果会丧失精度
- 如果前者超出了后者所能表示的范围,则是未定义的行为
注:对于,列表初始化和列表赋值,对于以下行为,将直接报错
- 可能会损失精度
- 由编译器实现定义的行为
- 未定义的行为
整数提升规则
- 值域小于等于 int 值域的类型转换为 int 类型
- 值域小于等于 unsigned int 值域的类型转化为 unsigned int 类型
浮点数提升规则
- float 类型转换为 double 类型
关于整数的等级说明:
- signed char < short < int < long < long long
- 无符号类型的等级和对应的有符号类型的等级相同
表达式中的算数类型的隐式转换规则
- 如果某一运算数是
long double
类型,将其它运算数转为long double
类型 - 如果某一运算数是
double
类型,将其它运算数转为double
类型 - 如果某一运算数是
float
类型,将其它运算数转为float
类型 - 其它情况,即两个运算数都是整数的情况:
- 首先,进行整数提升
- 提升后,如果两个运算数类型相同,直接计算
- 否则,如果两个运算数同为负数 或 同为正数,将等级小的类型转化为等级大的类型,然后计算
- 否则,如果无符号的运算数的等级大于等于有符号的运算数的等级,将有符号的运算数先转化为无符号的运算数,再计算
- 否则,如果有符号的运算数的类型的值域大于无符号的运算数的类型的值域,则,将无符号的运算数转换为有符号的运算数,再计算
- 否则,将两个运算数都转化为有符号数对应的无符号类型,然后计算
注:
- 浮点数之间的运算结果依旧是浮点数
- 无符号的整数之间的运算结果依旧是无符号的整数
- 有符号的整数之间的运算结果依旧是有符号的整数
注:在 C++11
中:
- 对于除法(
/
),结果将向0
取整,例如:-1/2 == 0
- 对于取模(
%
),除数的符号将忽略,例如:-5 % (-2) == -5 % 2 == -(5 % 2) == -1
出几个问题吧:
- 无符号的数参与的二元运算结果是否一定是无符号数?试一下以下代码
int a = -125;
unsigned char b = 1;
std::cout << (a + b) << std::endl;
2. 任何算数类型到无符号整数是不是都有明确定义?