(文章目录)
逻辑运算符
与运算(&)
A | B | A&B |
---|---|---|
False | False | False |
False | True | False |
True | False | False |
True | True | True |
或运算(|)
A | B | A | B |
---|---|---|
False | False | False |
False | True | True |
True | False | True |
True | True | True |
非运算(!)
A | !A |
---|---|
False | True |
True | False |
算数运算符
+、-、*、/、%、++、--.
- +、-还可以当做正负用,就不是算数运算符了,例如 -s 。
- ++、--只能是i++、i--,且是语句,不是表达式。也就是说,语句不能放到等式、函数参数等地方。例如, fmt.Println(a++) 是语法错误。Go语言没有++i、--i。
常量计算问题
常量分为typed类型化常量和untyped常量。
常量溢出
在进行整数常量计算时,如果结果超过了该类型所能表示的范围,就会发生常量溢出。例如下面的代码:
const a uint8 = 200 //uint8 无符号类型 取值范围[0,255]
const b = a + 100 // 常量溢出,编译报错
上述代码中,a 的类型为 uint8,表示的最大正整数是 255。而 a + 100 的结果为 300,超出了 uint8 能表示的范围,因此编译时会报错。
数据类型不同
GO是强类型语言,不同数据类型之间不能进行计算
var a int = 1
var b float32 = 2.3
fmt.Println(a * b) // 错误,int和float32类型不同,无法计算,除非强制类型转,Go语言中这种情况不会进行隐式类型转换
var a = 1 // 类型推导: int
var b = 2.3 // 类型推导: float64
fmt.Println(a * b) // 错误,int和float64类型不同,无法计算,除非强制类型转换
==上面的常量被赋给了变量,这些变量就确定了类型,虽然他们指向的值是字面常量,但是计算使用变量,但变量的类型不一致,报错。==
var a = 1 * 2.3 // 不报错
fmt.Printf("%T %v\n", a, a) // float64 2.3
==右边使用的都是字面常量,而字面常量都是无类型常量untyped constant,它会在上下文中隐式转换==
位运算符
按位与运算符(&)
两个相应的二进制位都为 1 时,结果才为 1。
var a = 60 // 0011 1100
var b = 13 // 0000 1101
var c = a & b // 0000 1100
按位或运算符(|)
两个相应的二进制位中只要有一个为 1 时,结果就是 1。
var a = 60 // 0011 1100
var b = 13 // 0000 1101
var c = a | b // 0011 1101
按位异或运算符(^)
两个相应的二进制位不同则结果为 1,否则为 0。
var a = 60 // 0011 1100
var b = 13 // 0000 1101
var c = a ^ b // 0011 0001
左移位运算符(<<)
把一个数的各二进制位全部左移若干位,高位丢弃,低位补 0。
var x = 1 // 0000 0001
var y = x << 1 // 0000 0010
右移位运算符(>>)
把一个数的各二进制位全部右移若干位,正号数左补 0,负号数左补 1。
var x = 4 // 0000 0100
var y = x >> 1 // 0000 0010
按位清空(&^ )
是一种按位清零的操作符。是先把右边按位取反后的值,再和左边位与,也就是右边有1的位的值不能保留,被清空,原 来是0的位被保留。换句话说,就是按照右边有1的位清空左边对应位
var a = 60 //0011 1100 0011 1100
var b = 18 //0001 0010 1110 1101
c := a &^ b // 0010 1100
比较运算符
==、!=、>、<、>=、<= 比较运算符组成的表达式,返回bool类型值。成立返回true,不成立返回false。
逻辑运算符
与运算符(&&)
当两个操作数都为 true 时,才返回 true,否则返回 false。
var a, b, c bool
a = true
b = false
c = a && b // 返回 false
或运算符(||)
只要有一个操作数为 true,就返回 true,否则返回 false。
var a, b, c bool
a = true
b = false
c = a || b // 返回 true
非运算符(!)
对一个操作数取反,如果原来为 true,则变成 false,如果原来为 false,则变成 true。
var a, b bool
a = true
b = !a // 返回 false
==注意==:Go 语言中的逻辑运算符具有短路特性。这意味着当表达式的结果可以确定时,计算过程将立即停止。例如,对于表达式 a && b,如果 a 为 false,则不需要计算 b 的值,因为整个表达式的结果已经可以确定为 false。这种机制可以提高程序的效率。
赋值运算符
等号(=)
将右侧操作数的值赋给左侧操作数。
var i int
i = 42
加等于(+=)
将左侧操作数和右侧操作数的和赋给左侧操作数。
var i int
i += 3 // 相当于 i = i + 3
减等于(-=)
将左侧操作数减去右侧操作数的差赋给左侧操作数。
var i int
i -= 3 // 相当于 i = i - 3
乘等于(*=)
将左侧操作数和右侧操作数的积赋给左侧操作数。
var i int
i *= 3 // 相当于 i = i * 3
除等于(/=)
将左侧操作数除以右侧操作数的商赋给左侧操作数。
var i int
i /= 3 // 相当于 i = i / 3
取模等于(%=)
将左侧操作数除以右侧操作数的余数赋给左侧操作数。
var i int
i %= 3 // 相当于 i = i % 3
左移等于(<<=)
将左侧操作数左移右侧操作数指定的位数,并将结果赋给左侧操作数。
var i = 4 // 0000 0100
i <<= 2 // 相当于 i = i << 2,即 0001 0000,即 16
右移等于(>>=)
将左侧操作数右移右侧操作数指定的位数,并将结果赋给左侧操作数。
var i = 128 // 1000 0000
i >>= 3 // 相当于 i = i >> 3,即 0001 0000,即 16
按位与等于 &
将左侧操作数和右侧操作数进行按位与运算,并将结果赋给左侧操作数。
var a = 174 // 1010 1110
var b = 59 // 0011 1011
a &= b // 等价于 a = a & b,即 00101010,即 42
按位异或等于 ^=
将左侧操作数和右侧操作数进行按位异或运算,并将结果赋给左侧操作数。
var a = 174 // 1010 1110
var b = 59 // 0011 1011
a ^= b // 等价于 a = a ^ b,即 10010101,即 149
按位或等于 |=
将左侧操作数和右侧操作数进行按位或运算,并将结果赋给左侧操作数。
var a = 174 // 1010 1110
var b = 59 // 0011 1011
a |= b // 等价于 a = a | b,即 10111111,即 191
==注意==赋值运算符的优先级较低,因此在使用复合赋值运算符时,要特别注意其结合顺序。例如,表达式 a += b * c 等价于 a = a + (b * c),而不是 a = (a + b) * c。建议在使用复合赋值运算符时,尽可能使用括号明确表达式的含义和结合顺序。
指针操作
数据是放在内存中,内存是线性编址的。任何数据在内存中都可以通过一个地址来找到它。
取地址操作符(&)
取地址操作符 & 可以返回一个变量的地址,并生成一个指向该变量的指针。
间接引用操作符(*)
间接引用操作符 * 可以返回一个指针所指向的变量的值。
==注意==:在 Go 语言中,指针不支持指针运算(如加减),也不支持随意转换为整数类型。另外,使用指针时,要特别注意指针的有效性,避免出现空指针异常。若需要使用 nil 指针,可以使用空指针常量 nil 来代替。
优先级
Category | Operator | Associativity |
---|---|---|
Postfix后缀 | () [] -> . ++ - - | Left to right |
Unary单目 | + - ! ~ ++ - - (type)* & | sizeof Right to left |
Multiplicative乘除 | * / % | Left to right |
Additive加减 | + - | Left to right |
Shift移位 | << >> | Left to right |
Relational关系 | < <= > >= | Left to right |
Equality相等 | == != | Left to right |
Bitwise AND | & | Left to right |
Bitwise XOR | ^ | Left to right |
Bitwise OR | | | Left to right |
Logical AND | && | Left to right |
Logical OR | || | Left to right |
Assignment赋值 | = += -= *= /= %=>>= <<= &= ^= |= | Right to left |
Comma逗号运算符 | , | Left to right |
规则:
- 表中优先级由高到低
- 单目 > 双目
- 算数 > 移位 > 比较 > 逻辑 > 赋值
- 搞不清,用括号,避免产生歧义
思考
15 & 5 和 15 &^ 5 有啥区别
15&5
15 1111
5 0101
0101
15&^5
5 0101
1010
15 1111
1010
==总结==:
- & 可以看做某位是1则该位保留其余位清除
- &^可以看做某位是1则该位清除其余位保留