zoukankan      html  css  js  c++  java
  • Swift24-高级运算符

    位运算符、溢出运算符、优先级和结合性、运算符函数、自定义运算符。

    Swift中的算术运算符默认是不会溢出的。所有的溢出行为都会被捕获并报告为错误。如果想让系统允许溢出行为,可以使用Swift中另一套默认支持溢出的运算符,比如溢出加法运算符(&+)。所有的这些溢出运算符都是以&开头的。

    在Swift中可以自由地定义中缀、前缀、后缀和赋值运算符,以及相应的优先级和结合性。这些运算符在代码中可以像预定义的运算符一样使用,我们甚至可以扩展已有的类型以支持自定义的运算符。

    位运算符

    位运算符可以操作数据结构中的每个独立的比特位。

    Swift支持C语言中的全部运算符,解下来会一一介绍。

    按位取反运算符:

    按位取反运算符(~)可以对一个数值的全部比特位进行取反

    按位取反运算符是一个前缀运算符,需要直接放在运算的数之前。并且它们之间不添加任何空格。

    按位与运算符:

    按位与运算符(&)可以对两个数的比特位进行1合并。它返回一个新的数,只有当两个数的对应位都为1的时候,新数的对应位才为1。

    按位或运算符:

    按位或运算符(|)可以对两个数的比特位进行比较。它返回一个新的数,只要两个数的对应位中有任意一个为1时,新数的对应位就为1。

    按位异或运算符:

    按位异或运算符(^)可以对两个数的比特位进行比较。它返回一个新的数,当两个数的对应位不同时,新数的对应位就为1。

    按位左移、右移运算符:

    按位左移运算符(<<)和按位右移运算符(>>)可以对一个数的所有位进行指定位数的左移和右移,但是需要遵守下面定义的规则。

    对一个数进行按位左移或按位右移,相当于对这个数进行乘以2或除以2的运算。将一个整数左移一位,等价于将这个数乘以2;将一个整数右移一位,等价于将这个数除以2。

    无符号整数的移位运算:

    对无符号整数进行移位的规则如下:

    1)已经存在的位按指定的位数进行左移和右移。

    2)任何因移动而超出整型存储范围的位都会被丢弃

    3)用0来填充移位后产生的空白位

    这种方法称为逻辑移位。

    有符号整数的移位运算:

    对比无符号整数,有符号整数的移位运算相对复杂得多,这种复杂性源于有符号整数的二进制表现形式。

    有符号整数使用第1个比特位(通常被称为符号位)来表示这个数的正负。符号位为0代表正数,为1代表负数

    其余的比特位(通常被称为数值位)存储了实际的值。有符号正整数和无符号数的存储方式是一样的,都是从0开始算起。

    负数用补码计算实际值。

    有符号整数的右移有一个额外的规则:

    1)当对整数进行按位右移运算时,遵循与无符号整数相同的规则,但是对于移位产生的空白位使用符号位进行填充,而不是0

    溢出运算符:

    在默认情况下,当向一个整数赋予超过它容量的值时,Swift默认会报错,而不是生成一个无效的数。这个行为为运算过大或者过小的数的时候提供了额外的安全性。

    也可以选择让系统在数值溢出的时候采取截断处理,而非报错。可以使用Swift提供的三个运算符来让系统支持整数溢出运算。这些运算符都是以&开头的:

    1)溢出加法 &+

    2)溢出减法 &-

    3)溢出乘法 &*

    数值溢出:

    数值有可能出现上溢或者下溢。

    var unsignedOverflow = UInt8.max

    //255

    unsignedOverflow = unsignedOverflow &+ 1

    //此时unsignedOverflow等于0

    优先级和结合性:

    运算符的优先级使得一些运算符优先于其它运算符,高优先级的运算符会先被计算。

    结合性定义了相同优先级的运算符是如何结合的,也就是说,是与左边结合为一组,还是与右边结合为一组。可以将理解为“它们是与左边的表达式结合的”或者“它们是与右边的表达式结合的”。

    在复合表达式的运算符顺序中,运算符的优先级和结合性是非常重要的。

    2 + 3 % 4 * 5

    //17

    可用括号结合子运算。括号内的优先级高于括号外。

    运算符函数

    类和结构体可以为现有的运算符提供自定义的实现,这通常被称为运算符重载。

    struct Vector2D{

      var x=0.0, y=0.0

    }

    extension Vector2D{

      static func + (left: Vector2D, right: Vector2D) -> Vector2D{

        return Vector2D(x: left.x + right.x, y: left.y + right.y)

      }

    }

    //重载了+运算符,在这个函数中,输入参数分别命名为left和right,代表在+运算符左边和右边的两个实例。

    前缀和后缀运算符:

    类与结构体也能提供标准单目运算符的实现。单目运算符只运算一个值。当运算符出现在值之前时,它就是前缀的(例如-a),而当它出现在值之后时,它就是后缀的(例如b!)。

    要实现前缀或者后缀运算符,需要在声明运算符函数的时候在func关键字之前指定prefix或者postfix修饰符:

    extension Vector2D{

      static prefix func - (vector: Vector2D) -> Vector2D{

        return Vector2D(x: -vector.x, y: -vector.y)

      }

    }

    //这段代码为Vector2D类型实现了单目符号运算符。由于该运算符是前缀运算符,所以这个函数需要加上prefix修饰符。

    复合赋值运算符:

    复合赋值运算符(=)与其它运算符进行结合

    例如,将加法与赋值结合成加法赋值运算符(+=)。在实现的时候,需要把运算符的左参数设置成inout类型,因为这个参数的值会在运算符函数内直接被修改。

    extension Vector2D{

      static func += (left: inout Vector2D, right: Vector2D){

        left = left + right

      }

    }

    注意:不能对默认的赋值运算符(=)进行重载。只有组合赋值运算符可以被重载。同样地,也无法对三目条件运算符(?:)进行重载。

    等价运算符:

    自定义的类和结构体没有对等价运算符进行默认实现,等价运算符通常被称为“相等”运算符(==)与“不等”运算符(!=)。对于自定义类型,Swift无法判断其是否相等。

    为了使用等价运算符能对自定义的类型进行判等运算,需要为其提供自定义实现,实现的方法与其它中缀运算符一样:

    extension Vector2D{

      static func == (left: Vector2D, right: Vector2D) -> Bool{

        return (left.x == right.x) && (left.y == right.y)

      }

      static func != (left: Vector2D, right: Vector2D) -> Bool{

        return !(left == right)

      }

    }

    自定义运算符:

    新的运算符要使用operator关键字在全局作用域内进行定义,同时还要指定prefix, infix 或者 postfix 修饰符

    prefix operator +++ {}

    //定义了一个新的名为+++的前缀运算符。

    extension Vector2D{

      static prefix func +++ (vector: inout Vector2D) -> Vector2D {

        vector += vector

        return vector

      }

    }

    //这里的+++运算符定义为类型的属性翻倍

    自定义中缀运算符的优先级:

    每个自定义中缀运算符都属于优先级组。这个优先级组指定了这个运算符和其它中缀运算符的优先级和结合性

    而没有明确放入优先级组的自定义中缀运算符会放到一个默认的优先级组内,其优先级高于三元运算符。

    以下例子定义了一个新的自定义中缀运算符 +- ,此运算符属于 AdditionPrecedence 优先组:

    infix operator +-: AdditionPrecedence

    extension Vector2D{

      static func +- (left: Vector2D, right: Vector2D) -> Vector2D{

        return Vector2D(x:left.x+right.x, y:left.y-right.y)

      }

    }

    这个运算符把两个向量的x值相加,同时用第一个向量的y值减去第二个向量的y值。因为它本质上属于“相加型”运算符,所以将它放置 +和- 等默认的中缀“相加型”运算符相同的优先级组中。

    注意:当定义前缀与后缀运算符的时候,并没有指定优先级。然而,如果对同一个值同时使用前缀与后缀运算符,则后缀运算符会先参与运算

  • 相关阅读:

    20145309《网络对抗》网络欺诈技术防范
    ceshi
    20145306 网路攻防 web安全基础实践
    20145306 张文锦 网络攻防 web基础
    20145306张文锦 网络欺诈技术防范
    20145306 《网络攻防》 信息搜集与漏洞扫描
    20145306 《网络攻防》 MSF基础应用
    20145306张文锦《网络对抗》恶意代码分析
    20145306 《网络攻防》 免杀技术
  • 原文地址:https://www.cnblogs.com/cjj-ggboy/p/12879646.html
Copyright © 2011-2022 走看看