04-运算符——算数运算符、关系运算符、逻辑运算符、位运算符、特殊运算符以及其优先级和结合性

运算符

算数运算符、关系运算符、逻辑运算符、位运算符、特殊运算符以及其优先级和结合性

一、算术运算符

1.1 算术运算符列表

  • +:加法运算,取正。
  • -:减法运算,取负。
  • *:乘法运算。
  • /:除法运算。
  • %:取模(求余)运算。
  • ++:自加1运算。
  • --:自减1运算。

注意事项

  • 取正:一目加法运算,如+a
  • 取负:一目减法运算,如-a
  • 取模运算:左右两个操作数必须是整型
  • 自加/自减运算
    • 可以操作整型、浮点型、指针类型。
    • 前缀(如++a):先自加/自减,然后参与表达式运算。
    • 后缀(如a++):先参与表达式运算,然后再自加/自减。

1.2 示例代码

#include <stdio.h>

int main() {
    int a = 5;
    int c = 3;

    // 除法和取模运算
    printf("5/3 = %d, 5%%3 = %d\n", a / c, a % c);  

    // 后缀自加
    printf("a++: %d\n", a++); // 输出5,a变为6

    // 前缀自加
    printf("++a: %d\n", ++a); // 输出7,a变为7

    // 演示一目取负
    int b = -100;
    printf("-b: %d\n", -b); // 输出100

    return 0;
}

输出示例

5/3 = 1, 5%3 = 2
a++: 5
++a: 7
-b: 100

解释:

  1. 除法和取模运算

    printf("5/3 = %d, 5%%3 = %d\n", a / c, a % c);
    
    • 5 / 3 结果为 1(整型除法)。
    • 5 % 3 结果为 2(取模运算)。
  2. 后缀自加

    printf("a++: %d\n", a++);
    
    • 输出 5,然后 a 自加 1 变为 6
  3. 前缀自加

    printf("++a: %d\n", ++a);
    
    • a 先自加 1 变为 7,然后输出 7
  4. 一目取负

    int b = -100;
    printf("-b: %d\n", -b);
    
    • -b 结果为 100,表示取反操作。

二、关系运算符

关系运算符用于比较两个值,结果是布尔值(真或假)

运算符描述示例结果描述
>大于a > b判断a是否大于b
<小于a < b判断a是否小于b
>=大于等于a >= b判断a是否大于或等于b
<=小于等于a <= b判断a是否小于或等于b
==等于a == b判断a是否等于b
!=不等于a != b判断a是否不等于b

在这些关系运算符中,表达式的结果为布尔值(真或假),用于条件判断。例如:

  • a == b:判断a是否等于b。

注意:

  • 判断两个数是否相等使用的== , 是两个等号 ,而不是一个
  • 关系运算符的表达式值为布尔值
  • 在数学中100< a <200 , 在代码中需要拆开 ,a > 100 && a < 200。

示例代码

#include <stdio.h>

int main() {
    int a = 100;
    int b = 200;

    printf("a > b: %d\n", a > b);        // 输出 0(假)
    printf("a < b: %d\n", a < b);        // 输出 1(真)
    printf("a >= b: %d\n", a >= b);      // 输出 0(假)
    printf("a <= b: %d\n", a <= b);      // 输出 1(真)
    printf("a == b: %d\n", a == b);      // 输出 0(假)
    printf("a != b: %d\n", a != b);      // 输出 1(真)

    return 0;
}

输出结果

a > b: 0
a < b: 1
a >= b: 0
a <= b: 1
a == b: 0
a != b: 1

三、逻辑运算符

逻辑运算符用于组合或反转布尔值。

运算符描述示例结果描述
!逻辑反!(x > 9)如果x大于9,则表达式为假;反之为真
&&逻辑与a > 100 && a < 200两边表达式同时为真则为真,否则为假
||逻辑或a > 100 || a < 200任意一边表达式为真则为真
==判断两个数是否相等a == b判断a是否等于b

注意:

在逻辑与的运算中,如果左边为假则直接判断为假,右边的表达式将不会执行
在逻辑或的运算中, 如果左边为真则表达式直接判断为真, 右边的表达式将不会

3.1 示例代码

#include <stdio.h>

int main() {
    int a = 100;
    int b = 200;

    printf("!(a > 50): %d\n", !(a > 50));  // 输出 0(假)
    printf("a > 50 && a < 200: %d\n", a > 50 && a < 200);  // 输出 1(真)
    printf("a > 150 || a < 50: %d\n", a > 150 || a < 50);  // 输出 0(假)

    // 逻辑运算符的短路特性
    if (a < 50 && (b = b + 300)) {
        // 如果左边为假,则右边不被执行
    }
    printf("a = %d, b = %d\n", a, b); // a = 100, b = 200

    if (a > 50 || (b = b + 300)) {
        // 如果左边为真,则右边不被执行
    }
    printf("a = %d, b = %d\n", a, b); // a = 100, b = 200

    return 0;
}

输出结果:

!(a > 50): 0
a > 50 && a < 200: 1
a > 150 || a < 50: 0
a = 100, b = 200
a = 100, b = 200

四、 位运算符

下面是位运算符的示例说明:

运算符描述示例结果描述
~位逻辑反~a对a进行按位取反
&位逻辑与a & b对a和b的每一位进行逻辑与操作
|位逻辑或a | b对a和b的每一位进行逻辑或操作
^位逻辑异或a ^ b对a和b的每一位进行逻辑异或操作
<<左移a << 4对a的二进制表示向左移动4位
>>右移a >> 2对a的二进制表示向右移动2位

注意:位运算符操作的是操作数的每一个二进制位。

4.1 详细举例说明

下面是对位运算符的详细描述:

  • ~(位逻辑反):位逻辑反操作符对操作数的每个二进制位进行取反操作,即将0变为1,将1变为0。
  • 例如
  • 如果a的二进制表示是 0000 0000 0000 0000 0000 0000 0000 0011
  • ~a的结果是 1111 1111 1111 1111 1111 1111 1111 1100

  • &(位逻辑与):位逻辑与操作符对操作数的每个二进制位进行逻辑与操作。如果两个操作数的对应位都为1,则结果的对应位为1,否则为0。
  • 例如:
  • 如果a的二进制表示是 0011b的二进制表示是 0101
  • a & b的结果是 0001

  • |(位逻辑或):位逻辑或操作符对操作数的每个二进制位进行逻辑或操作。如果两个操作数的对应位中至少有一个为1,则结果的对应位为1,否则为0。例如,如果a的二进制表示是 0011b的二进制表示是 0101,则a | b的结果是 0111

  • ^(位逻辑异或):位逻辑异或操作符对操作数的每个二进制位进行逻辑异或操作。如果两个操作数的对应位相同,则结果的对应位为0,如果不同则为1。例如,如果a的二进制表示是 0011b的二进制表示是 0101,则a ^ b的结果是 0110

  • <<(左移):左移操作符将操作数的二进制表示向左移动指定的位数,并用0填充右侧的空位。例如,如果a的二进制表示是 0011,则a << 4的结果是 0011 0000

int a = 3 ;
a ‐> 0000 0000 0000 0000 0000 0000 0000 0011
a<<4 ‐> 0000 0000 0000 0000 0000 0000 0011 0000

在这里插入图片描述

  • >>(右移):右移操作符将操作数的二进制表示向右移动指定的位数,并丢弃右侧移出的位。对于无符号数,右侧空出的位用0填充;对于有符号数,右侧空出的位使用符号位填充。

在这里插入图片描述

注意:

左移(<<): 将操作数的二进制表示向左移动指定的位数,右侧空出的位补0。

右移(>>): 将操作数的二进制表示向右移动指定的位数,右侧空出的位使用0或符号位填充。对于无符号数,右侧空出的位用0填充;对于有符号数,右侧空出的位使用符号位填充。

五、特殊运算符

5.1 赋值运算符 =

赋值运算符 = 用于将右值赋给左值
左值必须是一个可以被修改的存储位置,例如变量,而不能是常量或无法直接赋值的类型(如数组)。
下面是一些示例和注意事项:

  • 初始化:

    int a, b;
    int x[5];
    
  • 示例 1:

    a = 100; // 正确,对变量 a 进行赋值
    
  • 错误示例:

    100 = a; // 错误,左值不能是常量
    x = 123; // 错误,数组不可以直接赋值
    
  • 连续赋值:

    a = b = 100; // 正确,先把 100 赋值给 b,再把 b 赋值给 a
    

5.2 复合运算符

复合运算符是将赋值与算术位运算结合在一起,简化代码并提高效率。
常见的复合运算符如下:

  • 加减乘除:

    a += b; // 相当于 a = a + b;
    a -= b; // 相当于 a = a - b;
    a *= b; // 相当于 a = a * b;
    a /= b; // 相当于 a = a / b;
    
  • 求余:

    a %= b; // 相当于 a = a % b;
    
  • 位运算:

    a &= b; // 相当于 a = a & b;
    a |= b; // 相当于 a = a | b;
    a ^= b; // 相当于 a = a ^ b;
    a >>= b; // 相当于 a = a >> b;
    a <<= b; // 相当于 a = a << b;
    

5.3 条件运算符(三目运算符)

条件运算符是唯一一个需要三个操作数的运算符。语法为:表达式1 ? 表达式2 : 表达式3
它根据表达式1的真假来决定整个表达式的值。

  • 语法:

    表达式1 ? 表达式2 : 表达式3;
    
    • 如果表达式1为真,整个表达式的值为表达式2。
    • 如果表达式1为假,整个表达式的值为表达式3。
  • 示例:

    int a = 100;
    int b = 250;
    int max = a > b ? a : b; // 如果 a > b 为真,max 的值为 a,否则为 b
    

5.4 总结表

运算符描述示例结果描述
=赋值运算符a = 100将 100 赋值给 a
+=加赋值a += b将 a + b 的值赋值给 a
-=减赋值a -= b将 a - b 的值赋值给 a
*=乘赋值a *= b将 a * b 的值赋值给 a
/=除赋值a /= b将 a / b 的值赋值给 a
%=取余赋值a %= b将 a % b 的值赋值给 a
&=位与赋值a &= b将 a & b 的值赋值给 a
|=位或赋值a |= b将 a | b 的值赋值给 a
^=位异或赋值a ^= b将 a ^ b 的值赋值给 a
>>=右移赋值a >>= b将 a 右移 b 位后的值赋值给 a
<<=左移赋值a <<= b将 a 左移 b 位后的值赋值给 a
?:条件运算符a > b ? a : b如果 a > b 为真,则取 a,否则取 b

注意:位运算符操作的是操作数的每一个二进制位。例如,~a 是对 a 的每一个二进制位取反,a & b 是对 a 和 b 的每一位进行逻辑与操作,a | b 是对 a 和 b 的每一位进行逻辑或操作,a ^ b 是对 a 和 b 的每一位进行逻辑异或操作,a << 4 是将 a 的二进制表示向左移动 4 位,a >> 2 是将 a 的二进制表示向右移动 2 位。

5.5 sizeof 运算符

sizeof 是一个用于计算变量或变量类型在内存中所占字节数的运算符。它看起来像一个函数,但实际上是一个编译时运算符。

5.5.1 使用示例:
  1. 计算变量类型的大小:

    printf("sizeof(long): %ld\n", sizeof(long)); // 计算 long 类型的大小
    
  2. 计算变量的大小:

    int a;
    printf("sizeof(a): %ld\n", sizeof(a)); // 计算变量 a 的大小
    
  3. 计算数组的大小:

    int buf[5];
    printf("sizeof(buf): %ld\n", sizeof(buf)); // 计算数组 buf 的大小
    
  4. 计算结构体的大小:

    struct node {
        int a;    // 4 bytes
        char b;   // 1 byte
        double c; // 8 bytes
    };
    
    printf("sizeof(struct node): %ld\n", sizeof(struct node)); // 计算结构体 node 的大小
    

注意事项

  • sizeof 计算的是变量或数据类型在内存中占用的字节数。
  • 对于不同的编译器或平台,数据类型的大小可能会有所不同。
  • 结构体的大小可能会受到内存对齐的影响。
5.5.2 示例代码和结果描述
#include <stdio.h>

int main() {
    // 计算基本类型的大小
    printf("sizeof(long): %ld\n", sizeof(long)); // 输出 long 类型的大小

    // 计算变量的大小
    int a;
    printf("sizeof(a): %ld\n", sizeof(a)); // 输出变量 a 的大小

    // 计算数组的大小
    int buf[5];
    printf("sizeof(buf): %ld\n", sizeof(buf)); // 输出数组 buf 的大小

    // 定义结构体并计算其大小
    struct node {
        int a;    // 4 bytes
        char b;   // 1 byte
        double c; // 8 bytes
    };

    printf("sizeof(struct node): %ld\n", sizeof(struct node)); // 输出结构体 node 的大小

    return 0;
}

预期输出

sizeof(long): 8
sizeof(a): 4
sizeof(buf): 20
sizeof(struct node): 16

注意,上述输出仅为示例,实际大小可能因编译器和系统架构的不同而有所变化。例如,在某些系统中,long 类型可能占用 4 个字节,而不是 8 个字节。结构体的大小也可能因内存对齐而有所不同

5.6 return 运算符

return 运算符用于退出函数。如果在主函数(main 函数)中遇到 return,则程序进程结束;如果在其他函数中遇到 return,则返回到被调用的位置。

5.6.1 语法
return [expression];
  • expression:可选。指定要返回的值,其类型必须与函数的返回类型匹配。
5.6.2 使用示例
  1. 在主函数中使用 return

    int main(int argc, char const *argv[]) {
        int a = 5;
        int b = 10;
        int sum = a + b;
        printf("Sum: %d\n", sum);
        return 0;  // 退出程序进程
    }
    
  2. 在其他函数中使用 return

    int add(int x, int y) {
        return x + y;  // 返回 x 和 y 的和
    }
    
    int main(int argc, char const *argv[]) {
        int result = add(5, 10);  // 调用 add 函数并返回结果
        printf("Result: %d\n", result);
        return 0;
    }
    

注意事项:

  • return 必须出现在函数体内部。
  • 如果函数声明了返回类型,则 return 语句必须返回相应类型的值。如果函数的返回类型是 void,则 return 语句不能返回任何值。
  • main 函数中,返回值通常为 0 表示程序成功结束,非 0 表示程序异常结束。
5.6.3 示例代码和结果描述
#include <stdio.h>

// 一个示例函数,用于计算两个整数的和
int add(int x, int y) {
    return x + y;  // 返回两个整数的和
}

int main(int argc, char const *argv[]) {
    // 在主函数中调用 add 函数并输出结果
    int result = add(5, 10);  // 调用 add 函数并将返回值赋给 result
    printf("Result: %d\n", result);  // 输出结果
    return 0;  // 退出程序进程
}

预期输出

Result: 15

在上述示例中:

  • add 函数返回两个整数的和。
  • main 函数中,调用 add 函数,并输出结果。
  • main 函数最后使用 return 0 退出程序进程,表示程序成功结束。

六、优先级与结合性

使用命令man operator可以查看到优先级:
在这里插入图片描述
在表达式中,当多个运算符同时出现时,运算符的优先级和结合性决定了运算的顺序。一般情况下,先计算优先级高的运算符,优先级相同的运算符根据结合性进行计算。

6.1 运算符优先级和结合性示例

  1. 算术运算符:乘除(*/)的优先级高于加减(+-)。
  2. 逻辑运算符:逻辑与(&&)的优先级高于逻辑或(||)。
  3. 赋值运算符:赋值(=)的优先级低于算术和逻辑运算符。

6.2 逗号表达式

逗号表达式用于在一条语句中包含多个表达式,逗号运算符的优先级最低。逗号表达式从左向右依次运算每个表达式,整个逗号表达式的值取决于最后一个表达式的值

6.2.1 语法
表达式1 = (表达式2, 表达式3, 表达式4......, 表达式n);
6.2.2 示例
#include <stdio.h>

int main() {
    int a = 10;
    int c = 250;

    // 逗号表达式:从左到右依次执行表达式,整个表达式的值是最后一个表达式的值
    int b = (a++, a = a + c, a, 300);
    
    printf("b: %d\n", b);  // 输出 b 的值
    printf("a: %d\n", a);  // 输出 a 的值
    
    return 0;
}

输出结果

b: 300
a: 261

说明

  • a++:先使用 a 的当前值(10),然后 a 自增,a 变为 11。
  • a = a + c:计算 a + c,即 11 + 250,结果为 261,并赋值给 a,所以 a 变为 261。
  • a:此时 a 的值是 261。
  • 300:整个逗号表达式的值取最后一个表达式的值,即 300。

注意事项

  • 逗号表达式从左向右依次运算每一个表达式。
  • 整个表达式的值取决于最后一个表达式的值。

练习:
在这里插入图片描述

练习1

    int a=10;
    int b=11;

    printf("a= %d,b= %d \n",a^b^a,a^b^b);
  • 33
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写的什么石山代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值