命名空间
变体
操作

比较运算符

来自 cppreference.cn
< c‎ | 语言

比较运算符是二元运算符,用于测试条件,如果条件在逻辑上为,则返回 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

目录

[编辑] 关系运算符

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

lhs < rhs (1)
lhs > rhs (2)
lhs <= rhs (3)
lhs >= rhs (4)
1) 小于表达式
2) 大于表达式
3) 小于或等于表达式
4) 大于或等于表达式

其中

lhs, rhs - 都是实数类型或都是指向对象类型的指针的表达式

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

如果 lhsrhs 是任何 实数类型 的表达式,则

  • 执行常用算术转换
  • 转换后的操作数的值以通常的数学意义进行比较(除非正零和负零比较相等,并且任何涉及 NaN 值的比较都返回零)

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

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

  • 指向不是数组元素的对象的指针被视为指向具有一个元素的数组的元素
  • 如果两个指针指向同一个对象,或都指向同一个数组末尾的下一个位置,则它们比较相等
  • 如果两个指针指向同一个数组的不同元素,则指向索引较大的元素的指针比较大。
  • 如果一个指针指向数组的元素,而另一个指针指向同一个数组末尾的下一个位置,则超出末尾的指针比较大
  • 如果两个指针指向同一个 struct 的成员,则指向 struct 定义中稍后声明的成员的指针比指向较早声明的成员的指针大。
  • 指向同一 union 的成员的指针比较相等
  • 所有其他指针比较都会调用未定义的行为
#include <assert.h>
int main(void)
{
    assert(1 < 2);
    assert(2+2 <= 4.0); // int converts to double, two 4.0's compare equal
 
    struct { int x,y; } s;
    assert(&s.x < &s.y); // struct members compare in order of declaration
 
    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); // different values
}

[编辑] 相等运算符

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

lhs == rhs (1)
lhs != rhs (2)
1) 等于表达式
2) 不等于表达式

其中

lhs, rhs - 表达式,其中
(自 C23 起)
  • 都是指向 兼容 类型的对象或函数的指针,忽略指向类型的限定符
  • 一个是对象指针,另一个是指向(可能限定的)void 的指针
  • 一个是对象或函数指针,另一个是空指针常量,例如 NULL nullptr(自 C23 起)

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

  • 如果两个操作数都具有算术类型,则执行常用算术转换,并且以通常的数学意义比较结果值(除非正零和负零比较相等,并且任何涉及 NaN 值的比较,包括与自身的相等性比较,都返回零)。 特别是,如果复数类型的实部比较相等且虚部比较相等,则它们相等。
(自 C23 起)
  • 如果一个操作数是指针,另一个是空指针常量,则首先将空指针常量转换为指针的类型(这会产生一个空指针值),然后比较两个指针,如下所述
  • 如果一个操作数是指针,另一个是指向 void 的指针,则将非 void 指针转换为指向 void 的指针,然后比较两个指针,如下所述
  • 如果以下任何一项为真,则两个指针比较相等
  • 它们都是其类型的空指针值
  • 它们都是指向同一个对象或函数的指针
  • 一个指针指向 struct/union/array 对象,另一个指针指向其第一个成员/任何成员/第一个元素
  • 它们都指向同一个数组的最后一个元素之后的下一个位置
  • 一个是数组末尾的下一个位置,另一个是较大数组中或没有填充的 struct 中跟随第一个数组的不同数组的开头

(与关系运算符一样,指向不是任何数组元素的对象的指针的行为类似于指向大小为 1 的数组的元素的指针)

[编辑] 注释

struct 类型的对象不会自动比较相等,并且使用 memcmp 比较它们并不可靠,因为填充字节可能具有任何值。

由于指针比较适用于指向 void 的指针,因此宏 NULL 可以在 C 中定义为 (void*)0,尽管这在 C++ 中是无效的,因为 void 指针不会隐式转换为类型指针

在比较浮点值的相等性时必须小心,因为许多运算的结果无法精确表示,必须进行舍入。 在实践中,浮点数通常在允许最后一位或多位单位的差异的情况下进行比较。

#include <assert.h>
int main(void)
{
    assert(2+2 == 4.0); // int converts to double, two 4.0's compare equal
 
    int n[2][3] = {1,2,3,4,5,6};
    int* p1 = &n[0][2]; // last element in the first row
    int* p2 = &n[1][0]; // start of second row
    assert(p1+1 == p2); // compare equal
 
    double d = 0.0/0.0; // NaN
    assert( d != d ); // NaN does not equal itself
 
    float f = 0.1; // f = 0.100000001490116119384765625
    double g = 0.1; // g = 0.1000000000000000055511151231257827021181583404541015625
    assert(f != g); // different values
}

[编辑] 参考文献

  • 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 关系运算符 (p: 95-96)
  • 6.5.9 相等运算符 (p: 96-97)
  • C99 标准 (ISO/IEC 9899:1999)
  • 6.5.8 关系运算符 (p: 85-86)
  • 6.5.9 相等运算符 (p: 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++ 文档 关于 比较运算符