跳到主要内容
版本:release

关系运算表达式

语法

形式语法
1表达式 == 表达式
2表达式 != 表达式
3表达式 < 表达式
4表达式 <= 表达式
5表达式 > 表达式
6表达式 >= 表达式

描述

关系运算表达式用于比较两个值的大小或相等性,结果是一个布尔值(truefalse)。

相等和不等(==, !=

如果 ==!= 的左右两侧的类型相同(或者都是数值类型,即 intfloat),且它们的 基类型是可以被比较的(int, float, raw_pointer, stringbuffer), 此时进行的是 比较 操作,即比较它们的值是否相等;比较的规则参见后文的 比较 章节。

对于不可比较的左右操作数,==!= 被用于检查它们是否是相同的实例。

mixed a = 15;
mixed b = 15;
mixed c = {};

write(a == b); // 此处在执行 `比较`,而不是判断它们是不是相同的实例
write(a != c); // true,a 和 c 不是同一个实例,类型不相同的两个值显然是不同的实例。
write(c == {}); // false,c 和 {} 不是同一个实例

mixed d = c;
write(c == d); // true,c 和 d 是同一个实例

比较(<, <=, >, >=, ==, !=

比较大小的关系运算符包括 <(小于)、<=(小于等于)、>(大于)和 >=(大于等于),相等 性运算符包括 ==(等于)和 !=(不等于)。

int, float, raw_pointer, stringbuffer 类型的值可以使用这些运算符进行比较。在 比较大小时,除了 intfloat 可以互相比较之外,关系运算符的两个操作数应该具有相同的 基类型,否则将导致编译/运行时错误。

不同类型的比较规则如下:

  • 数值类型(intfloat):比较其数值的大小,如果其中一个操作数是 float 且值为 nan, 所有比较结果都是 false

  • string:按字典序,逐字节地比较字符串的内容。

  • buffer:按字典序,逐字节地比较 buffer 的内容。

  • 对于原始指针或结构体类型(raw_pointer),比较规则更复杂一些:

    • 比较其注册的类型id
    • 如果两个操作数的类型id相同,且不为0,检查其是否有注册的比较方法,如果有,按照 注册的方法进行比较;否则按照id为0的情况处理:
    • 如果类型id为0,比较指向的内存地址的值

    目前 GS 没有对外提供注册比较方法的接口,内置有特定比较方法的类型只有表示网络地址和接口的 sockaddr 类型:

    • 比较两个 sockaddr 的协议,IPv4 小于 IPv6,如果相同,继续:
    • 比较两个 sockaddr 的地址,按照网络序表示法转化为协议对应的 uint32uint16[8] 进行比较,如果相同,继续:
    • 比较两个 sockaddr 的端口号

需要注意的是,如果参与比较的操作数包含 float,由于浮点数本身存在舍入规则和精度问题,可能导致 比较结果不符合预期:

write(0.1 + 0.2 == 0.3);    // false,按照默认的舍入规则,0.1 + 0.2 的结果
// 是一个近似于 0.3 的值,但不等于 0.3

示例

write(10 < 20);         // true
write(10 <= 10); // true
write(20 > 10); // true
write(20 >= 20); // true
write(10 == 10); // true
write(10 != 20); // true
write(10 == 10.0); // true
write(10 < 10.1); // true