C/ObjC/C++在数值溢出时并未做过多保护,责任推给了程序员。
- C/ObjC/C++选择相信程序员能控制溢出,不过有的编译器会提供溢出预防策略。
char c = 128; // 假设char是有符号1字节
- GCC/G++不会提示任何问题,gcc11.4即使用-Woverflow也不会有任何提示。
- Clang会提示警告:implicit conversion from 'int' to 'char' changes value from 128 to -128 - Go语言和C语言类似,选择相信程序员能控制溢出,发生溢出不会有任何错误。
- Swift是设计安全的语言,编译期间发现数值存储不匹配,会直接报错,运行期发现溢出也会报错
let a: UInt8 = -1
同时,Swift也提供了溢出运算符(如&+、&-、&*等)来显式处理可能溢出的情况。 - C#默认也不会对运行期溢出做处理,但可利用编译器选项/checked或者checked操作符/语句做全局、局部溢出检查,一旦发现溢出将抛出异常。
- 代码或者编译选择指定checked,一定会有溢出检查;如果代码中指定unchecked, 会忽略编译选项/checked.
- 注意,如果用常量赋值发生溢出,如short a = 32767,编译器会直接报错:常量值“32768”无法转换为“short”
- Java和C#一样常量赋值逃不过编译器检查,默认也不会对运行期溢出做处理,运行期可利用特定API做溢出检查,比如加法检查Math.addExact方法。
int a = Integer.MAX_VALUE;
try {
int result = Math.addExact(a, 1);
} catch (ArithmeticException e) {
System.out.println("Overflow exceptoin:" + e.getMessage());
} - Python 3用long替代int, long几乎是无穷大(除非计算机内存无法存储long字符串),数值溢出很少出现在Python.
- JS作为脚本语言,溢出是个很少考虑的话题。数值Number类型最大安全值MAX_SAFE_INTEGER超过万亿,如果不满足还可用更大的BigInt.
- VB.NET之前编译阶段不会提示溢出,运行期溢出会报错。VB.NET编译期即可报错。
- 例如:Dim bigNumber As Integer = Int32.MaxValue + 1
报错:常量表达式无法在类型“Integer”中表示。 - Rust作为一门安全放在首位的语言,编译期发现溢出会报错。
let a: u32 = u32::MAX + 1; // 报错:arithmetic operation will overflow- 同时Rust提供一系列API反馈是否会溢出、溢出后是回绕还是设定最大/最小值。
以加法为例,checked_add发生溢出返回None,overflowing_add返回溢出与否标志和计算值,saturating_add根据是上溢还是下溢设置为能表达的最大或最小值,wrapping_add会在发生溢出时回绕。
- 同时Rust提供一系列API反馈是否会溢出、溢出后是回绕还是设定最大/最小值。
- 仓颉 遇到溢出的字面量,一样会编译出错。
var i: UInt8 = 300
报错:the number '300' exceeds the value range of type 'UInt8' - PHP超出整数范围的数值会自动转换成浮点数以保证数值正确。
