Namespaces
Variants

Comparison operators

From cppreference.net

比较运算符是二元运算符,用于测试条件,若条件逻辑为 则返回 1 ,若条件为 则返回 0

运算符 运算符名称 示例 描述
== 等于 a == b a 等于 b
! = 不等于 a ! = b a 不等于 b
< 小于 a < b a 小于 b
> 大于 a > b a 大于 b
<= 小于等于 a <= b a 小于等于 b
>= 大于等于 a >= b a 大于等于 b

目录

关系运算符

关系运算符表达式的形式为

左操作数 < 右操作数 (1)
左操作数 > 右操作数 (2)
左操作数 <= 右操作数 (3)
左操作数 >= 右操作数 (4)
1) 小于表达式
2) 大于表达式
3) 小于或等于表达式
4) 大于等于表达式

其中

lhs , rhs - 两个表达式均具有实数类型或均具有指向对象类型的指针

任何关系运算符表达式的类型为 int ,其值(非左值)在指定关系成立时为 1 ,在指定关系不成立时为 0

如果 lhs rhs 是任意 实数类型 的表达式,则

  • 执行 常规算术转换
  • 转换后的操作数值按常规数学意义进行比较(正负零比较结果相等,涉及NaN值的所有比较均返回零)

注意,复数和虚数不能使用这些运算符进行比较。

如果 lhs rhs 是指针类型的表达式,它们必须都是指向 兼容类型 对象的指针,但所指向对象的限定符会被忽略。

  • 指向非数组元素的对象的指针,会被视为指向一个单元素数组的首元素
  • 若两个指针指向同一对象,或同时指向同一数组的尾后位置,则它们比较相等
  • 若两个指针指向同一数组的不同元素,则指向较大索引元素的指针比较结果更大
  • 若一个指针指向数组元素,另一个指针指向同一数组的尾后位置,则尾后指针比较结果更大
  • 若两个指针指向同一 结构体 的不同成员,则指向在结构体定义中较晚声明的成员的指针比较结果更大
  • 指向同一联合体不同成员的指针比较结果相等
  • 所有其他指针比较都会引发未定义行为
#include <assert.h>
int main(void)
{
    assert(1 < 2);
    assert(2+2 <= 4.0); // int转换为double,两个4.0比较相等
    struct { int x,y; } s;
    assert(&s.x < &s.y); // 结构体成员按声明顺序比较
    double d = 0.0/0.0; // NaN
    assert( !(d < d) );
    assert( !(d > d) );
    assert( !(d <= d) );
    assert( !(d >= d) );
    assert( !(d == d) );
    float f = 0.1; // f = 0.100000001490116119384765625
    double g = 0.1; // g = 0.1000000000000000055511151231257827021181583404541015625
    assert(f > g); // 不同的值
}

相等运算符

相等运算符表达式的形式为

lhs == rhs (1)
lhs != rhs (2)
(注:根据要求,HTML标签、属性及 标签内的运算符均未翻译,C++术语lhs/rhs保留原样,仅对结构编号添加了中文括号)
1) 等于表达式
2) 不等于表达式

其中

lhs , rhs - 满足以下任一条件的表达式:
  • 同时具有任意 算术类型 (包括复数类型和虚数类型)
(C23 起)
  • 同时指向 兼容类型 的对象或函数(忽略被指向类型的限定符)
  • 一个是指向对象的指针,另一个是指向(可能带限定符的) void 的指针
  • 一个是指向对象或函数的指针,另一个是空指针常量(如 NULL nullptr (C23 起)

任何相等运算符表达式的类型为 int ,其值(非左值)在指定关系成立时为 1 ,在指定关系不成立时为 0

  • 若两个操作数均具有算术类型,则执行 常规算术转换 ,并按常规数学意义比较结果值(但正负零比较相等,任何涉及NaN值的比较(包括与自身的相等性比较)均返回零)。特别地,若复数类型的实部比较相等且虚部比较相等,则这两个复数值相等。
(since C23)
  • 如果一个操作数是指针而另一个是空指针常量,该空指针常量首先 转换 为指针类型(得到空指针值),然后按以下规则比较两个指针
  • 如果一个操作数是指针而另一个是void指针,非void指针将 转换 为void指针,然后按以下规则比较两个指针
  • 满足以下任意条件时,两个指针比较结果相等:
  • 它们都是各自类型的空指针值
  • 它们都指向同一对象或函数
  • 一个指针指向结构体/联合体/数组对象,另一个指针指向其首成员/任意成员/首元素
  • 它们都指向同一数组的末元素后一位置
  • 一个指针指向某数组的末元素后一位置,另一个指针指向紧随其后的同类型数组(位于更大数组或无填充结构体中)的首元素位置

(与关系运算符类似,指向非任何数组元素的对象的指针,其行为如同指向大小为1的数组元素的指针)

注释

结构体类型的对象不会自动进行相等比较,使用 memcmp 进行比较也不可靠,因为填充字节可能包含任意值。

由于指针比较适用于指向 void 的指针,在 C 语言中宏 NULL 可被定义为 ( void * ) 0 ,但在 C++ 中该定义无效,因为 void 指针不能隐式转换为具体类型指针

在比较浮点数值是否相等时必须格外小心,因为许多运算结果无法精确表示而必须进行舍入。实际应用中,浮点数比较通常允许存在一个或多个最小精度单位的误差。

#include <assert.h>
int main(void)
{
    assert(2+2 == 4.0); // int转换为double,两个4.0比较相等
    int n[2][3] = {1,2,3,4,5,6};
    int* p1 = &n[0][2]; // 第一行最后一个元素
    int* p2 = &n[1][0]; // 第二行起始位置
    assert(p1+1 == p2); // 比较相等
    double d = 0.0/0.0; // NaN
    assert( d != d ); // NaN不等于其自身
    float f = 0.1; // f = 0.100000001490116119384765625
    double g = 0.1; // g = 0.1000000000000000055511151231257827021181583404541015625
    assert(f != g); // 不同的值
}

参考文献

  • C17 标准 (ISO/IEC 9899:2018):
  • 6.5.8 关系运算符 (p: 68-69)
  • 6.5.9 相等运算符 (p: 69-70)
  • C11 标准 (ISO/IEC 9899:2011):
  • 6.5.8 关系运算符 (页码: 95-96)
  • 6.5.9 相等运算符 (页码: 96-97)
  • C99标准(ISO/IEC 9899:1999):
  • 6.5.8 关系运算符(页码:85-86)
  • 6.5.9 相等运算符(页码:86-87)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 3.3.8 关系运算符
  • 3.3.9 相等运算符

参见

运算符优先级

常用运算符
赋值 自增
自减
算术 逻辑 比较 成员
访问
其他

a = b
a + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b

a [ b ]
* a
& a
a - > b
a. b

a ( ... )
a, b
( type ) a
a ? b : c
sizeof


_Alignof
(自C11起)
(至C23止)

alignof
(自C23起)

C++ 文档 关于 比较运算符