运算符分类

运算符是可以对数据进行运算的符号,比如+、-、*、/、%等符号。除了算术运算符之外,像取数据下标,括号函数调用等也是运算符。

运算符操作的对象称为操作数,运算符与操作数组合成表达式。表达式结尾没有分号,如果在表达式两边加上一个括号,那么表达式最终可以得到一个值,这是表达式与语句的区别。
Alt text

使用运算符与表达式的时候,以下几点要注意:

  • 操作数个数
    具有一个操作数的被称之一元运算符,两个操作数的称为二元运算符,三个操作数的称为三元运算符。对于二元运算符,位于运算符左侧的称为左值,位于运算符右侧的称为右值。
  • 操作数类型
  • 运算结果的类型
  • 运算符优先级
  • 结合方向

C语言中的运算符定义很宽,除数值运算符外,取地址,解地址,赋值(=)等都可以看成运算符,以下是C语言中运算符的各类:

  • 算术运算符
    • 五则运算:+ - * / %
    • 取反运算符:-
    • 自增与自减运算符:++ --
  • 关系运算符
    • 大于、大于等于:> >=
    • 小于、小于等于:< <=
    • 等于: ==
    • 不等于: !=
  • 逻辑运算符
    • 逻辑与: &&
    • 逻辑或: ||
    • 逻辑非: !
  • 赋值运算符:=及其扩展赋值运算符
  • 条件运算符:? :
  • 指针运算符
    • 取地址:&
    • 解地址:*
  • 求字节运算符:sizeof
  • 位运算符
    • 左移:<<
    • 右移:>>
    • 按位与:&
    • 按位或:|
    • 按位取反:~
    • 按位异或:^
  • 成员运算符:.
  • 下标运算符:[]
  • 逗号运算符: ,
  • sizeof

运算符优先级表

摘抄自《C语言深度解剖(第2版)》,优先级越小越高。
Alt text
Alt text

注:

  1. 同一优先级的运算符,运算次序由结合方向所决定。
  2. 解决优先级与运算方向困惑的最好办法是使用括号,推荐多使用括号。

算术运算符

包括:

  1. 五则运算:+ - * / %
  2. 取反运算符:-
  3. 自增与自减运算符:++ --

注意点:

  1. * / %具有同一优先级,+ - 具有同一优先级,前者优先级高于后者,同一优先级下,运算顺序从左向右。
  2. %(取模运算)的操作数不可以是浮点数
  3. 自增自减运算符只能用于变量,不能用于常量和表达式,类似5--,(a+b)++的写法都是不对的。
  4. 自增自减运算符作前缀与后缀时是有区别的,作前缀时先运算再取值,作后缀时先取值再运算,如下:
    c = a++; 等效于 c = a; a++;
    c = ++a; 等效于 a++; c = a;

关系运算符

包括:

  1. 大于、大于等于:> >=
  2. 小于、小于等于:< <=
  3. 等于: ==
  4. 不等于: !=

注意点:

  1. 只可以对标量类型进行关系运算。(标量类型包括算术类型与指针,与之对应的是聚合类型,包括数组与结构体)。
  2. 关系运算的结果是真或假。C语言中,假用数值0来表示,真则可以用任何非0的值来表示,特殊地,对于关系运算,真用1来表示,既关系运算的结果只能是0或1。

逻辑运算符

注意点:

  1. 赋值用 '=' 表示,判断相等用 '==' 表示,注意区分两者。
  2. 赋值运算的结果是右值,即 (a = 3) 的值是3。
  3. 赋值运算的结合方向是从右向左,类似 a = b = c = 3 的计算方式是 a = (b = (c = 3))。

逗号运算符

C语言中,逗号也是运算符的一种,类似下面这样的表达式是允许的:

a = (3, 4);

(a > 0, a = 1)

(printf(“hello”), 1, 3)

逗号运算是C语言中优先级最低的运算符,所有表达式从左往右依次计算,逗号运算的结果是最后一个表达式的值。

选择运算符

表达式1 ? 表达2 :表达3
a > b ? a : b

sizeof

sizeof是一个特殊的运算符,用于判断变量或类型的大小,通过sizeof计算出的大小默认为long类型,如下:

#include <stdio.h>

int main()
{
    printf("sizeof(char) = %ld\n", sizeof(char));     // 1
    printf("sizeof(int) = %ld\n", sizeof(int));       // 4
    printf("sizeof(double) = %ld\n", sizeof(double)); // 8

    int a;
    printf("sizeof(a) = %ld\n", sizeof(a)); // 4
}

注意一点,sizeof可以接受表达式作为参数,比如sizeof(a++),但是sizeof并不会执行这个表达式,它只会判断出表达式结果的类型并返回其大小,也就是sizeof(a++)并不会使a自增。

  • 无标签