一.运算前 - 操作数类型对齐

当两个不同类型的操作数(例如 intdouble)进行运算时,编译器首先会执行寻常算术转换,将它们提升到共同兼容的类型。

规则:总是提升到精度和范围最大的类型

在算术运算中,编译器遵循以下优先级(简化版):

操作数类型 1 操作数类型 2 共同的运算类型 (结果) 示例 (A+B)
int double double 被提升为 double,然后进行 double 加法。
float long double long double 都被提升为 long double
short int int 被提升为 int,然后进行 int 加法。
int unsigned int unsigned int int 被提升为 unsigned int。(注意:这可能导致意想不到的结果,需谨慎!)

二.运算后 - 结果类型赋值

一旦计算完成,结果会有一个类型(由阶段一决定),但最终它必须被存储到一个变量中。这个存储变量的类型决定了最终的值。

规则:结果的类型取决于接收变量的类型

这里可能发生两种情况:

A.结果类型 接收变量类型 (安全/提升)

如果运算结果的类型小于或等于接收变量的类型,那么结果会被安全地存储或提升到接收变量的类型。

int a = 10;
int b = 3;

// 阶段一: int / int -> 运算结果类型是 int (3)
// 阶段二: 接收变量 double result
double result = a / b;
// 赋值: 结果 (int 3) 被提升并存储为 double 3.0
// result 的值: 3.0

B.结果类型 接收变量类型 (窄化/降级)

如果运算结果的类型大于接收变量的类型,数据可能会丢失(精度丢失或数值溢出)。这被称为窄化转换。

示例 1: 浮点数精度丢失

double a = 10.0;
int b = 3;

// 阶段一: double / int -> 运算结果类型是 double (3.333...)
// 阶段二: 接收变量 int result
int result = a / b;
// 赋值: double 结果被强制转换为 int。小数部分 (.333...) 被截断。
// result 的值: 3

示例 2: 显式控制(Casting 的重要性)
为了避免阶段一的整数截断,我们需要在运算前使用 static_cast 强制提升操作数的类型:

int a = 10;
int b = 3;

// 阶段一: static_cast<double>(a) / b -> double / int -> 运算结果类型是 double (3.333...)
// 阶段二: 接收变量 double result
double result = static_cast<double>(a) / b;
// result 的值: 3.33333...