命名空间
变体
操作

比较运算符

来自 cppreference.com
< c‎ | language

比较运算符是二元运算符,用于测试条件,如果该条件在逻辑上为 **真**,则返回 **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 是指针类型的表达式,则它们必须都是指向 兼容类型 对象的指针,但指向对象的限定符将被忽略。

  • 指向不是数组元素的对象的指针将被视为指向具有一个元素的数组的元素。
  • 如果两个指针指向同一个对象,或者都指向同一个数组的末尾,则它们比较相等。
  • 如果两个指针指向同一个数组的不同元素,则指向索引更大的元素的指针将进行更大的比较。
  • 如果一个指针指向数组的元素,而另一个指针指向同一个数组的末尾,则末尾指针将进行更大的比较。
  • 如果两个指针指向同一个 结构体 的成员,则指向在结构体定义中声明较后的成员的指针将进行比指向声明较前的成员的指针更大的比较。
  • 指向同一个联合的成员的指针比较相等。
  • 所有其他指针比较都会引发未定义的行为。
#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 的指针,然后对这两个指针进行比较,如下所述。
  • 如果满足以下任何条件,则两个指针比较相等。
  • 它们都是其类型的空指针值。
  • 它们都是指向同一个对象或函数的指针。
  • 一个指针指向结构体/联合/数组对象,而另一个指向其第一个成员/任何成员/第一个元素。
  • 它们都指向同一个数组的最后一个元素之后。
  • 一个指向数组的末尾,而另一个指向不同数组(相同类型)的开头,该数组在更大数组中紧随其后,或者在没有填充的结构体中紧随其后。

(与关系运算符一样,指向不是任何数组元素的对象的指针将被视为指向大小为 1 的数组的元素)。

[编辑] 备注

结构体类型的对象不会自动比较相等,并且使用 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 起)

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