数值类型运算后值溢出会发生什么?

数值类型运算后值溢出会发生什么

1.无符号整型溢出时,值为0

func main()
{
	var x1 uint64 = math.MaxUint64
	var y1 uint64 = 1
	//无符号整型溢出
	addUint(x1, y1)
}
func addUint(x, y uint64) {
	sum := x + y
	fmt.Println("addUint:", sum)
	fmt.Printf("addUint %b \n", sum)
}

2.有符号整型溢出,值出现反转

fun main()
{
	//有符号整数运算时出现溢出
	var x2 int64 = math.MaxInt64
	var y2 int64 = 1
	addInt(x2, y2)
}
func addInt(x, y int64) {
	sum := x + y
	fmt.Println("addInt64: ", sum, "max int64", math.MaxInt64)
}

运行结果:
C:\Users\admin\AppData\Local\Temp\GoLand\___go_build_main_go.exe
addInt64:  -9223372036854775808 max int64 9223372036854775807

3.常量值不允许溢出

4.数值类型转换时需要考虑溢出问题
下面展示一些 内联代码片

func main()
{
	var x4 int32 = math.MaxInt32
	y4 := int16(x4)
	fmt.Println("y4:", y4)
	if (x4 < math.MinInt16) || (x4 > math.MaxInt16) {
		// 错误处理
	}
}

5.整型转换时出现符号丢失

func main()
{
	var x5 int32 = math.MinInt32
	y5 := uint32(x5)
	fmt.Println("x5:", x5, "y5:", y5)
	if x5 < 0 {
		// 错误处理
	}
}
运行结果:
C:\Users\admin\AppData\Local\Temp\GoLand\___go_build_main_go.exe
addInt64:  -9223372036854775808 max int64 9223372036854775807

6.浮点型溢出后为最大值

func main()
{
	x := math.MaxFloat64
	y := float64(1000)
	z := x + y
	fmt.Println("z:", z, "math.MaxFloat64:", x, x == z)
}
运行结果
C:\Users\admin\AppData\Local\Temp\GoLand\___go_build_main_go.exe
z: 1.7976931348623157e+308 math.MaxFloat64: 1.7976931348623157e+308 true

7.浮点数的其它情况

func main()
{
	//x1 := float64(0.4)
	//y1 := float64(0.5)
	//fmt.Println("x1+y1=", x1+y1) //x1+y1= 0.9
	//x2 := float64(0.3)
	//y2 := float64(0.6)
	//fmt.Println("x2+y2=", x2+y2) //x+y= 0.899999999999999
	x3 := float64(0.1)
	y3 := float64(0.2)
	fmt.Println("x3+y3=", x3+y3, "0.1+0.2=", 0.1+0.2) //x3+y3= 0.30000000000000004 0.1+0.2= 0.3

	//如果使用常量,这种情况就不会发生精度损失。
	//const c1 = 0.3
	//const c2 = 0.6
	//fmt.Println("c1+c2=", c1+c2, "c1 type:", reflect.TypeOf(c1))

	//浮点数不满足结合率
	var x = 0.3
	var y = 0.6
	var z float64 = 0.1
	fmt.Println("(x+y)+z:", (x+y)+z, "x+(y+z):", x+(y+z))

	//四舍但不一定五入
	fmt.Printf("%.2f\n", 9.824)
	fmt.Printf("%.2f\n", 9.8250)
	fmt.Printf("%.2f\n", 9.8251)

	fmt.Printf("%f\n", float32(1)/float32(3)) //0.333333
	fmt.Printf("%f\n", float32(1/3))          //0.000000

	var f1 float32 = -1.123456789
	f2 := -1.123456789
	fmt.Println("f1:", f1, "f2:", f2) //f1: -1.1234568 f2: -1.123456789
}
<think>好的,我现在需要回答用户关于C语言中int和unsigned int混合运算的问题。首先,我得回忆相关的类型转换规则。记得在C语言中,当有号和无整数混合运算时,会发生类型提升,可能是有号转换为无号,这可能会导致一些意想不到的结果,比如负数变成很大的正数。 然后,我需要确定转换的具体规则。根据C标准,当两个整数类型不同但等级相同时,比如int和unsigned int,有类型会转换为无类型。这就是所谓的“通常的算术转换”。这一步很关键,因为很多错误都是由于这种隐式转换导致的。 接下来,我应该举几个例子来说明这种情况。例如,当int是负数时,转换成unsigned int后的会变成该负数加上UINT_MAX + 1。比如,-1转换成unsigned int就是UINT_MAX。这可能导致比较或运算结果与预期不。 然后,我需要考虑混合运算的具体情况,比如加减乘除或者比较操作。比如,当比较一个int和unsigned int时,int会被转换为unsigned,如果原来的int是负数,就会变成很大的正数,导致比较结果错误。比如,-1 < 1U的结果会是false,因为-1被转换成UINT_MAX,显然大于1。 另外,我需要给出一些代码示例来展示这种情况。例如,写一个简单的程序,其中int和unsigned int相加,并输出结果,或者比较它们的大小,展示结果如何变化。 还需要解释为什么会这样设计。可能的原因是为了保持运算的一致性,避免类型混乱,但这也带来了潜在的风险,需要程序员特别注意类型转换的问题。 最后,要提醒用户如何避免这类问题,比如显式地进行类型转换,或者确保操作数类型一致,避免隐式转换带来的错误。同时,在编写比较表达式时,要特别注意操作数的类型,特别是当其中一个是无号时。 总结一下,回答的结构应该是先说明转换规则,再举例说明现象,给出代码示例,解释结果的原因,最后给出避免问题的建议。然后按照用户的要求,提出几个相关问题,比如类型提升规则、类型转换的影响、如何避免陷阱,以及无溢出的处理等。</think><< 在C语言中,当 `int` 和 `unsigned int` 混合运算时,编译器会按照「通常的算术转换」(Usual Arithmetic Conversions)规则将操作数转换为统一的类型。具体行为如下: 1. **隐式类型转换**: - 如果两个操作数的类型不同但属于同一类别(例如都是整数),则「等级较低」的类型会被转换为「等级较高」的类型。 - `int` 和 `unsigned int` 的等级相同,因此会根据「号性」决定最终类型: - 若其中一个操作数是 `unsigned int`,则另一个操作数会被转换为 `unsigned int`。 - 如果 `int` 的为负数,转换时会基于补码规则将其视为一个很大的正整数(例如 `-1` 转换为 `UINT_MAX`)。 2. **运算示例**: ```c int a = -5; unsigned int b = 10; if (a < b) { // 实际会转换为:将 a 转换为 unsigned int(为 UINT_MAX - 4),此时条件为 false } ``` 3. **潜在风险**: - 负数转换到无类型可能导致数值意外增大。 - 比较操作(如 `int` 和 `unsigned int` 的比较)可能产生反直觉的结果。 **总结**:混合运算时,`int` 会被隐式转换为 `unsigned int`,可能导致逻辑错误。建议显式强制类型转换或保持操作数类型一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值