short在算术运算中总是变成int,因为c++标准规定小于int的整型参与表达式前必须提升为int(若能完整表示)或unsigned int,这是语言规则而非编译器优化。

short 在算术运算中为什么总是变成 int
因为 C++ 标准规定:所有小于 int 的整型(包括 short、signed char、unsigned char)在参与表达式计算前,必须先提升为 int(如果 int 能完整表示原类型值),否则提升为 unsigned int。这不是编译器优化,而是语言规则。
常见错误现象:short a = 32767; short b = 1; auto c = a + b; —— 此时 c 的类型是 int,不是 short;哪怕你用 decltype(a + b) 查,结果也是 int。
- 这个提升发生在每个操作数上,独立于运算符左右侧是否同类型
- 即使两个
short相加,结果也绝不会是short;赋值给short变量时才发生截断 - 函数重载时,
void f(int)比void f(short)更容易被选中,因为short到int是“整型提升”,属于最佳匹配
什么时候 short 会保持原类型不提升
只有不参与“值计算”的上下文里,short 才可能保留本体类型。典型场景是取地址、sizeof、typeid、模板参数推导(非表达式语境)。
使用场景举例:sizeof(short) 返回 2(通常),&a 得到的是 short*,不是 int*;但一旦写成 sizeof(a + 0),就变成 sizeof(int)。
立即学习“C++免费学习笔记(深入)”;
-
template<typename t> void g(T); g(a);</typename>→T推导为short(因为实参是左值,不触发提升) -
template<typename t> void h(T); h(a + b);</typename>→T推导为int(因为a + b是纯右值表达式,已提升) - 结构体内成员声明为
short,内存布局中仍占 2 字节,但访问该成员做运算时,读出后立刻提升
强制保持 short 运算的常见误操作和替代方案
有人试图用 static_cast<short>(a) + static_cast<short>(b)</short></short> 来“维持 short 类型”,这是无效的——提升规则在隐式转换之前就生效了,两个 static_cast 结果仍是 short,但相加前各自又被提升为 int。
真正想避免提升,只能绕开二元运算符本身:
- 用复合赋值(如
a += b;)——左侧变量类型不变,但右侧仍先提升再计算,最后截断回short,有溢出风险 - 手动截断:
short c = static_cast<short>(a + b);</short>,但需自己确保不溢出(short范围通常是 −32768 ~ 32767) - 若目标是节省内存或对齐,应优先考虑结构体打包(
#pragma pack或[[no_unique_address]]),而非依赖运算类型
不同平台下 short 提升行为是否一致
是的,只要符合 ISO/IEC 14882 标准,short 的整型提升规则完全一致。但要注意:提升目标类型取决于 int 的宽度。
例如在某些嵌入式平台(如 16 位系统),sizeof(int) == 2,此时 unsigned short 若为 16 位,则可能无法被 int 完整表示,从而提升为 unsigned int。不过现代主流平台(x86/x64/ARM64)基本都是 int ≥ 32 位,所以 short 总是提升为 int。
- 不能依赖
sizeof(short) == sizeof(int)做类型等价判断 -
CHAR_BIT、SHRT_MAX等宏定义来自<climits></climits>,比硬编码更安全 - 跨平台代码中,若需确定宽度,优先用
int16_t替代short,它明确保证 16 位且有符号
constexpr 计算都逃不掉。










