关系运算表达式
语法
| 形式 | 语法 |
|---|---|
| 1 | 表达式 == 表达式 |
| 2 | 表达式 != 表达式 |
| 3 | 表达式 < 表达式 |
| 4 | 表达式 <= 表达式 |
| 5 | 表达式 > 表达式 |
| 6 | 表达式 >= 表达式 |
描述
关系运算表达式用于比较两个值的大小或相等性,结果是一个布尔值(true 或 false)。
相等和不等(==, !=)
如果 == 或 != 的左右两侧的类型相同(或者都是数值类型,即 int 或 float),且它们的
基类型是可以被比较的(int, float, raw_pointer, string 和 buffer),
此时进行的是 比较 操作,即比较它们的值是否相等;比较的规则参见后文的 比较 章节。
对于不可比较的左右操作数,== 和 != 被用于检查它们是否是相同的实例。
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, string 和 buffer 类型的值可以使用这些运算符进行比较。在
比较大小时,除了 int 与 float 可以互相比较之外,关系运算符的两个操作数应该具有相同的
基类型,否则将导致编译/运行时错误。
不同类型的比较规则如下:
-
数值类型(
int和float):比较其数值的大小,如果其中一个操作数是float且值为nan, 所有比较结果都是false。 -
string:按字典序,逐字节地比较字符串的内容。 -
buffer:按字典序,逐字节地比较buffer的内容。 -
对于原始指针或结构体类型(
raw_pointer),比较规则更复杂一些:- 比较其注册的类型id
- 如果两个操作数的类型id相同,且不为0,检查其是否有注册的比较方法,如果有,按照 注册的方法进行比较;否则按照id为0的情况处理:
- 如果类型id为0,比较指向的内存地址的值
目前 GS 没有对外提供注册比较方法的接口,内置有特定比较方法的类型只有表示网络地址和接口的
sockaddr类型:- 比较两个
sockaddr的协议,IPv4 小于 IPv6,如果相同,继续: - 比较两个
sockaddr的地址,按照网络序表示法转化为协议对应的uint32和uint16[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