C
语言
头文件
类型支持
程序工具
变参数函数支持
动态内存管理
错误处理
日期和时间工具
字符串库
算法
数值
输入/输出支持
本地化支持
线程支持 (C11)
原子操作 (C11)
技术规范
C 语言
基本概念
关键词
预处理器
语句
表达式
初始化
声明
函数
杂项
C 的历史
技术规范
表达式
通用
值类别
求值顺序与顺序点
常量表达式
隐式转换
泛型选择
常量及字面量
整数常量
浮点常量
字符常量
字符串字面量
复合字面量
运算符
运算符优先级
成员访问与间接
逻辑运算符
比较运算符
算术运算符
赋值运算符
自增减
函数调用、逗号、条件运算符
sizeof
_Alignof(C11)
转型运算符
比较运算符是二元运算符,它们测试条件,而若条件逻辑上为真则返回 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 。
若 lhs 和 rhs 是任何实数类型表达式,则
进行通常算术转换
以通常数学意义比较运算数转换后的值(除了正零与负零比较相等,而任何涉及 NaN 的比较返回零)
注意不能用这些运算符比较复数和虚数。
若 lhs 和 rhs 是指针类型表达式,则它们必须都是指向兼容类型对象的指针,除了忽略被指向对象上的限定。
指向非数组元素的指针被当做如同它是指向有一个元素的数组的首元素的指针
若二个指针指向同一对象,或都指向同一数组的尾后一位置,则它们比较相等
若二个数组指向同一数组的不同元素,则指向有较大下标的元素的指针比较大于另一者。
若一个指针指向数组元素,而另一指针指向同一数组的尾后一位置,则尾后一位置指针比较大于前者
若二个指针指向同一联合体的成员,则指向结构体声明中较后声明的成员的指针,比较大于指向较先声明的成员的指针。
指向同一联合体成员的指针比较相等
所有其他指针比较引起未定义行为
运行此代码
#include
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) );
float f = 0.1; // f = 0.100000001490116119384765625
double g = 0.1; // g = 0.1000000000000000055511151231257827021181583404541015625
assert(f > g); // 不同值
}
等于运算符
等于运算符拥有形式
lhs == rhs
(1)
lhs != rhs
(2)
1) 等于表达式
2) 不等于表达式
其中
lhs, rhs
-
下列表达式之一:
都拥有任何算术类型(包括复数和虚数)
都是指向兼容类型对象或函数的指针,忽略被指向类型的限定符
一个是指向对象指针,而另一个是指向(可有限定的) void
一个是指向对象或函数指针,而另一个是如 NULL 的空指针常量
任何等于运算符表达式的类型为 int ,而当指定关系成立时其值(非左值)为 1 ,而当指定关系不成立时其值为 0 。
若两个运算数都拥有算术类型,则进行通常算术转换,而以通常数学意义比较结果值(除了正零和负零比较相等,而任何涉及 NaN 值的比较,包括与自身的相等,都返回零)。特别是若复数类型值的实部比较相等且虚部比较相等,则它们相等。
若一个运算数为指针而另一空指针常量,则首先转换空指针常量为该指针的类型(给出空指针值),并以后述方式比较二个指针
若一个运算数是指针而另一者为指向 void 的指针,则转换非 void 指针为指向 void 指针,并以后述方式比较二个指针
若下列为真,则二个指针比较相等:
它们都是其类型的空指针值
它们都是指向相同对象的指针
一个指针指向结构体/联合体/数组对象,而另一个指向其首成员/任何成员/首元素
它们都是指向同一数组末元素后一位置的指针
一个是数组尾后一位置指针,另一个指向(同类型)的相异数组起始,而后一数组在更大的数组或无填充的结构体中后随前一数组
(同关系运算符,指向非数组元素的指针表现同指向大小为 1 的数组元素的指针)
注意
不能自动比较结构体类型对象,而通过 memcmp 比较它们不可靠,因为填充字节可拥有任何值。
因为指针比较能用于指向 void 的指针,故 C 中可定义宏 NULL 为 (void*)0 ,不过 C++ 中这会非法,因为其中 void 指针不可隐式转换为有类型指针。
比较浮点值是否相等时应谨慎,因为许多运算的结果无法准确表示,而必须舍入。实践中,通常以允许最后位置相差一或多个单位的方式比较浮点数。
运行此代码
#include
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); // 不同值
}
引用
C11 standard (ISO/IEC 9899:2011):
6.5.8 Relational operators (p: 95-96)
6.5.9 Equality operators (p: 96-97)
C99 standard (ISO/IEC 9899:1999):
6.5.8 Relational operators (p: 85-86)
6.5.9 Equality operators (p: 86-87)
C89/C90 standard (ISO/IEC 9899:1990):
3.3.8 Relational operators
3.3.9 Equality operators
参阅
运算符优先级
常用运算符
赋值
自增自减
算术
逻辑
比较
成员访问
其他
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
? :
sizeof
_Alignof (C11 起)