操作符详解

目录

一、操作符分类

二、算术操作符

三、移位操作符

四、位操作符

五、逻辑操作符

六、表达式求值


一、操作符分类

操作符可以分为:算术操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符、逗号表达式、下标引用函数调用和结构成员操作符等

二、算术操作符

1.算数操作符主要包括:

+(加)    -(减)   *(乘)   /(除)   %(取模,取余数)

2.注意事项

(1)除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。

(2)对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法,例如4/1.0或4.0/1都执行浮点数除法。

(3)% 操作符的两个操作数必须为整数。返回的是整除之后的余数。

(4)负数的取模计算方式与编译器有关,例如-7%3可以等于-1也可以等于-2

三、移位操作符

1.原码、反码与补码

首先,正数的原反补码完全相同,负数的原反补码遵循以下规则:

原码:数据的二进制代码,代表了变量的值属性

反码:除符号位全部按位取反

补码:反码加一,在只要在内存中存储和程序使用数据时都改变补码

2.左移操作符:

(1)移位规则:左边抛弃、右边补0

3.右移操作符:>>

(1)移位规则:包括算术右移和逻辑右移两种方式,两种方式的选取取决于编译器

(2)算术右移:右边抛弃,左边补齐符号位

(3)逻辑右移:右边抛弃,左边直接补零

注意:移位操作符的操作数只能是非负整数。

四、位操作符

1.位操作符主要包括:

& (按位与)| (按位或)^ (按位异或)

2.规则

(1)& 按位与规则:二进制补码对应位均为1时,新产生的二进制代码为1否则为0

(2)| 按位或的规则:二进制补码对应位有一个为1时,新产生的二进制代码为1否则为0

(3)^ 按位异或的规则:二进制补码对应位不相同时时,新产生的二进制代码为1否则为0

(4)对于两个变量a和b,存在a^0=a,a^a=0,。

(5)多个^的表达式计算值与计算顺序无关而且也满足交换律,比如:a^b^b=a^(b^b)=a^0=a

3.面试题

不能创建临时变量(第三个变量),实现两个数字的交换。

#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d,b=%d", a, b);
	a = a ^ b;
	b = a ^ b;//此时的a相当于原来的a^b
	a = a ^ b;//此时的b=a,a依旧相当于原来的a^b
	printf("交换后:a=%d,b=%d", a, b);
	return 0;
}

五、逻辑操作符

&&(逻辑与) ||(逻辑或)

逻辑与是在前后表达式均为真时整个表达式为真,逻辑或是在前后表达式有一个为真时整个表达式为真

区分逻辑与和按位与:1&2----->0 、1&&2---->1

区分逻辑或和按位或:1|2----->3 、1||2---->1

C语言中0为假,非零为真。

六、单目操作符及其他操作符

!           逻辑反操作

-           负值

+           正值

&           取地址

sizeof      操作数的类型长度(以字节为单位)

~           对一个数的二进制按位取反

--          前置、后置--

++          前置、后置++

*           间接访问操作符(解引用操作符,用于指针)

(类型)       强制类型转换

还有其他操作符,可以看看我之前的博客(偷懒):拒绝从入门到入土:初识C语言_聪明的骑士的博客-CSDN博客icon-default.png?t=M5H6https://blog.csdn.net/qq_65285898/article/details/124021746?spm=1001.2014.3001.5502

六、表达式求值

1.整型提升与数据截断

C的整型算术运算总是至少以缺省整型类型的精度来进行的。

为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。

比如说两个字符型变量相加就需要把这两个变量转化为int类型(整型提升),然后再进行相加,最后再将结果转化为字符类型(截断)。

//负数的整形提升
char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//无符号整形提升,高位补0

2.算数转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

比如:一个int类型的变量与一个double类型的变量相加,结果为double类型。也就是说,不同类型的数据运算,在其计算时变量的大小至少为一个整形大小,结果默认为精度较高的数据类型。

3.操作符的属性

(1)复杂表达式的求值有三个影响的因素。

  • 操作符的优先级:规定了相邻操作符的执行顺序
  • 例如:a+b*c中由于*的优先级高于+,所以先执行*后执行+
  • 操作符的结合性:相邻的两个运算符的具有同等优先级时,决定表达式的结合方向,有些需要让表达式从左向右计算(L-R),有些需要从右向左计算(R-L),还有些并不适用(N/A)
  • 例如:a=b=c中由于前后操作符相同,也就是说优先级相同,而=的结合性为R-L,也就是操作符从右到左执行,相当于a=(b=c)把c赋值给b,然后a=b把b赋值给a,这就是操作符的结合性。
  • 是否控制求值顺序:最具代表性的是逻辑操作符。
  • 例如对于exp1 && exp2的条件,exp1为假时exp2是不会计算的,同样对于exp1 || exp2的条件,exp1为真时exp2也是不会计算的。

(2)附表:

(3)由于操作符的优先级适用于相邻操作符,所以复杂表达式的值在不同的编译器下是不同的。

比如:

#include<stdio.h>
int main()
{
    int i = 10;
    i = i-- - --i * ( i = -3 ) * i++ + ++i;
    printf("i = %d\n", i);
    return 0; 
}

在不同环境下i = i-- - --i * ( i = -3 ) * i++ + ++i的计算结果:

Tandy 6000 Xenix 3.2

-128

Think C 5.02(Macintosh)

-95

IBM PowerPC AIX 3.2.5

-86

Sun Sparc cc(K&C编译器)

-85

gcc,HP_UX 9.0,Power C 2.0.0

-63

所以,在我们写代码的时候注意避免过于复杂的表达式。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值