文章目录
作为基本运算符的补充,Swift 提供了一些对数值进行复杂运算的高级运算符。它们包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。
与 C 的算术运算符不同,Swift 中算术运算符默认不会溢出。溢出行为都会作为错误被捕获。想要允许溢出行为,可以使用 Swift 中另一套默认支持溢出的运算符,比如溢出加法运算符 &+。所有这些溢出运算符都是以 & 符号开始的。
定义结构体、类和枚举时,为这些自定义类型也提供 Swift 标准的运算符将会非常有用。Swift 简化了这些运算符的定制实现,运算符也会针对不同类型使用对应的实现。
你不会被限制在预定义的运算符里。Swift 允许你自由地定义中缀、前缀、后缀和赋值运算符,以及相对应的优先级和结合性。这些运算符可以像预定义的运算符一样使用,你甚至可以扩展已有类型来支持自定义的运算符。
位运算符
位运算符可以操作数据结构中每一个独立的比特位。它们通常被用在底层开发中,比如图形编程和创建设备驱动。位运算符在处理外部资源的原始数据时也非常有用,比如为自定义的通信协议的数据进行编码和解码。
Swift 支持 C 里面所有的位运算符。
按位取反运算符
按位取反运算符( ~ )是一个前缀运算符,对一个数值的全部比特位进行取反:
let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 等于 0b11110000
使用二进制值 00001111 初始化了一个 UInt8 类型的整数 initialBits,前四位全是 0 ,后四位都是 1 。使用按位取反运算符创建一个新的常量名为 invertedBits ,initialBits 所有位都被取反,invertedBits 的值是 11110000。
按位与运算符
按位与运算符( & )可以对两个数的比特位进行合并。它会返回一个新的数,只有当两个数的对应比特位位都是 1 的时候,新数对应的比特位才为 1。
在下面的例子中, firstSixBits 和 lastSixBits 的中间四个位都为 1 。按位与可以把它们合并为一个新值 00111100:
let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8 = 0b00111111
let middleFourBits = firstSixBits & lastSixBits // 等于 0b00111100
按位或运算符
按位或运算符( | )可以对两个比特位进行比较,然后返回一个新的数,只要两个操作位任一为 1,新数对应的比特位就为 1。
在下面的例子中, someBits 和 moreBits 在不同的位设置了 1 。位或运算符把它们合并为 11111110:
let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // 等于 0b11111110
按位异或运算符
按位异或运算符( ^ )可以对两个数的比特位进行比较,当两个操作数的对应比特位不相同时,薪数对应的比特位就为 1。
在下面的例子中, firstBits 和 otherBits 的值有一位设置为 1 ,而对方设置为 0 。按位异或运算符会将这两个位上的值设置为 1 , firstBits 和 otherBits 其他位都设置为了 0 :
let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // 等于 0b00010001
按位左移、右移运算符
按位左移运算符(<<)和 按位右移运算符(>>)可以对一个数的所有位进行指定位数的左移和右移,但是需要遵守下面定义的规则:
将一个整数左移一位,等价于将这个数乘以 2,同样地,将一个整数右移一位,等价于将这个数除以 2。
无符号整数的移位运算
对无符号整数的移位规则如下:
已经存在的比特位按指定的位数进行左移和右移。
任何因移动而超出整型存储范围的位都会被丢弃。
用 0 来填充向左或向右移动后产生的空白位。
这种方法称为逻辑移位。
下面的代码展示了 Swift 中的移位运算:
let shiftBits: UInt8 = 4 // 即二进制的 0b00000100
var shiftedBits = shiftBits << 1 // 0b00001000
shiftedBits = shiftBits << 2 // 0b00010000
shiftedBits = shiftBits << 5 // 0b10000000
shiftedBits = shiftBits << 6 // 0b00000000
shiftedBits = shiftBits >> 2 // 0b00000001
可以使用移位操作对其他的数据类型进行编码和解码:
let pink: UInt32 = 0xCC6699
let redComponent = (pink & 0xFF0000) >> 16 // redComponent 是 0xCC, 即 204
let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent 是 0x66, 即 102
let blueComponent = pink & 0x0000FF // blueComponent 是 0x99, 即 153
这个示例使用了一个命名为 pink 的 UInt32 常量来存储层叠样式表(CSS)中粉色的颜色值。该 CSS 的颜色值 #CC6699 , 在 Swift 中表示为十六进制 0xCC6699 。然后利用按位与运算符和位右移运算符从这个颜色值中分解出 红 CC、绿 66 以及 蓝 99 三个部分。
红色部分通过对 0xCC6699 和 0xFF0000 进行按位与运算得到 0xCC0000。然后,再将这个数按向右移动 16 位得到 0xCC,也就是十进制数值的 204。
同样的,绿色部分通过对 0xCC6699 和 0x00FF00 进行按位与运算得到 0x006600。然后将这个数向右移动 8 位,得到 0x66,也就是十进制数值的 102。
最后&