C语言之操作符篇

目录

一、操作符分类

二、二进制

1.进制转换

        10进制转2进制:模二除二,余数反读

        2进制转10进制:每位乘权重,求和

        2进制转8进制:3位转1位

        2进制转16进制:4位转1位

2.原码、反码、补码

        正数

        负数

3.移位操作符

        <<操作符

        >>操作符

4.位操作符

        &(按位与)

        |(按位或)

        ^(按位异或)

        ~(按位取反)

三、逗号表达式

1.用法

2.作用

四、下标访问和函数调用

1.下标访问

2.函数调用

五、结构体访问

1.操作符  .  

2.操作符  ->  

六、操作符属性

1.优先级

2.结合性

七、表达式求值

1.整形提升

        整形提升的含义

        整型提升的规则

        整型提升的意义

2.算术转换

八、问题表达式

1.问题表达式示例

        示例一

        示例二

2.问题表达式解决

        使用括号

        拆表达式


一、操作符分类

        算术操作符+- * / %

        移位操作符 <<>>

        位操作符& | ^ ~

        赋值操作符= += -= *= /= %= <<= >>= &=|=^=

        单⽬操作符:++--&*+-~ sizeof(类型)

        关系操作符> >= < <= == !=

        逻辑操作符&& ||

        条件操作符? :

        逗号表达式:  

        下标引⽤[ ]

        函数调⽤: ( )

        结构成员访问: ->

        下面我们主要介绍二进制相关操作符、逗号表达式、下标引用、函数调用、结构成员访问


二、二进制

1.进制转换

        10进制转2进制:模二除二,余数反读

        对n循环%2、/2直到n为零,将得到的余数倒序输出

        2进制转10进制:每位乘权重,求和

        二进制从低位开始,每一位依次乘2的k次方(k=0,1,2...),对所有结果求和

        注:第一位从2的零次方开始!

#include<stdio.h>

//十进制转二进制
void ten_two(int x)
{
	int arr[32] = { 0 };
	int i = 0;
	//模2除2
	while (0 != x)
	{
		arr[i++] = x % 2;
		x /= 2;
	}
	//倒序输出
	for (i = 31; i >= 0; i--)
	{
		printf("%d", arr[i]);
		if (i % 4 == 0)
		{
			printf(" ");
		}
	}
	printf("\n");
}


//二进制转十进制
void two_ten(int x)
{
	int ret = 0;
	int i = 0;
	while (0 != x)
	{
		int pow = 1;
		//计算权重
		for (int j = 0; j < i; j++)
		{
			pow *= 2;
		}
		i++;
		//求和
		ret = ret + x % 10 * pow;
		x /= 10;
	}
	printf("%d\n", ret);
}
int main()
{
	ten_two(15);//输出:0000 0000 0000 1111
	two_ten(1111);//输出:15
	return 0;
}

        2进制转8进制:3位转1位

        000——0                001——1                010——2                011——3

        100——4                101——5                110——6                111——7

        2进制转16进制:4位转1位

        0000——0                0001——1               0010——2                      0011——3

        0100——4                0101——5               0110——6                      0111——7

        1000——8               1001——9               1010——A(10)                1011——B(11)

        1100——C(12)         1101——D(13)        1110——E(14)                1111——F(15)

2.原码、反码、补码

        有符号整数分为包含符号位数值位两部分。在二进制中,最高位为符号位(0表示正,1表示负),其余位为数值位

        正数

        原码、反码、补码均相同

        负数

        原码:直接将数值按照正负形式翻译为二进制

        反码:符号位不变,其他位按位取反

        补码:反码+1

        注:补码转原码,原码转补码均可用“取反+1”

-13
原码:1000 0000 0000 1101
反码:1111 1111 1111 0010
补码:1111 1111 1111 0011

       在计算机系统中,数据统一用补码来存储。

        原因:1.CPU只有加法器,利用补码可以将加法和减法统一处理;2.原码和补码相互转换的运算过程相同,不需要额外的硬件电路

3.移位操作符

        <<操作符

        左边丢弃,右边补零(左移一位——>乘2

        >>操作符

        1.逻辑右移:左边补零,右边丢弃

        2.算数右移:左边补原来符号位,右边丢弃(右移一位——>除以2

#include<stdio.h>


int main()
{
    //左移操作符
	int n = 10;
	printf("%d\n", n);//输出:10
	printf("%d\n", n << 1);//输出:20
	return 0;
}

左移操作符演示

#include<stdio.h>

int main()
{
	//右移操作符
	int n = 10;
	printf("%d\n", n);//输出:10
	printf("%d\n", n >> 1);//输出:5
	return 0;
}

逻辑右移演示

算术右移演示

        注:不要用移位操作符移动负数位,这个是标准未定义的!

int n = 10;
n << -1;//错误的用法

4.位操作符

        &(按位与)

        有0则为0。将两个整形转换为二进制补码,若对应位置上,两数有一个为0,则结果的对应位置也为0

        |(按位或)

        有1则为1。将两个整形转换为二进制补码,若对应位置上,两数有一个为1,则结果的对应位置也为1 

        ^(按位异或)

        相同为0,相异为1。有0则为0。将两个整形转换为二进制补码,若对应位置上两数相同,则结果的对应位置为0,否则为1

        ~(按位取反)

        包括符号位,全部取反(取反一次——>乘-1加-1

        注:所有按位运算结果均为补码,输出时应转换为原码

#include<stdio.h>

int main()
{
	int a = -3;
	int b = 5;
	printf("%d\n", a & b);//输出:5
	printf("%d\n", a | b);//输出:-3
	printf("%d\n", a ^ b);//输出:-8
	printf("%d\n", ~a);//输出:2
	return 0;
}

        一些二级结论


三、逗号表达式

1.用法

语句,语句,……,语句

        返回值为最后一个表达式的结果

2.作用

        有利于简化过程,防止代码冗余

//不用逗号表达式
a = GetVal();
CountVal(&a);
while (a > 0)
{
    //业务处理
    a = GetVal();
    CountVal(&a);
}


//使用逗号表达式
while (a = GetVal(),CountVal(&a), a>0)
{
    //业务处理
}

四、下标访问和函数调用

1.下标访问

        操作数:一个数组名+一个索引值

arr[5]//操作数为arr和5

        原则上数组名和索引值可以交换顺序,但为了方便理解,我们通常不这么写

5[arr]//不建议此种写法,等价于arr[5]

2.函数调用

        操作数:函数名+实参

test();
test(a);
test(a,b,c……);

        实参可以为0个,但必须有且仅有一个函数名


五、结构体访问

1.操作符  .  

        用法:结构体变量名.成员名

#include<stdio.h>

//结构体声明
typedef struct Point
{
	int x;
	int y;
}Point;


int main()
{
	Point n = { 123,456 };
	Point* pn = &n;
	printf("%d %d\n", n.x, n.y);//输出:123 456
	printf("%d %d\n", (*pn).x, (*pn).y);//输出:123 456
}

2.操作符  ->  

        用法:结构体指针->成员名

#include<stdio.h>

//结构体声明
typedef struct Point
{
	int x;
	int y;
}Point;


int main()
{
	Point n = { 123,456 };
	Point* pn = &n;
	printf("%d %d\n", pn->x, pn->y);//输出:123 456
}

六、操作符属性

1.优先级

        含义:一个表达式有多个操作符时,决定先进行哪个操作的规则

        常用操作符优先级:

常用操作符优先级
1()
2++、--
3+、-(单目)
4*、/(双目)
5+、-(双目)
6==、>、<等关系操作符
7=、+=、-=等赋值操作符

2.结合性

        含义:当在一个表达式中连续使用多个相同优先级的操作符时,决定这些操作符应该如何结合或分组的规则

        大部分操作符都是左结合(从左到右执行),只有少部分操作符为右结合(从右到左执行),比如赋值操作符。

        参考文档:C 运算符优先级 - cppreference.com


七、表达式求值

1.整形提升

        整形提升的含义

        字符(char)和短整型(short)操作数在使用前被转换为普通整形

        整型提升的规则

        按照变量数据类型的符号位补充,负数则全补1,正数则全补0

char a = -1;
//原型:
//1111 1111
//整形提升为:
//1111 1111 1111 1111


char a = 1;
//原型:
//0000 0001
//整形提升为:
//0000 0000 0000 0001

        整型提升的意义

        CPU的通用寄存器长度为int类型字节长度。CPU难以实现8比特字节位直接相加,所以表达式中各种长度可能小于int类型的整型值,都必须转换成intunsigned int,才能送入CPU中运算

char a, b, c;
……
a + b;
//a和b先转换提升为int类型,然后将两个int相加,最后将结果截断为char类型

2.算术转换

        当表达式中的各操作数类型不同时,需将各操作数转换为相同类型,否则操作无法进行

        规则:低字节向高字节转换


八、问题表达式

1.问题表达式示例

        示例一

a*b + c*d + e*f

        路径一:先将乘法a*b、c*d、e*f全部算出来,最后将结果相加

        路径二:先计算两个乘法a*b、c*d,结果相加,再计算e*f,所有结果相加

        当前面的运算会影响后面的运算时,这种运算顺序未定的表达式,最终得到的结果是无法预料的!

        示例二

int a = 3;
a + --a;

        左操作数的获取在右操作数之前还是之后不定,结果可能为3 + 2,也可能为2 + 2

2.问题表达式解决

        使用括号

        使用括号将运算顺序不定的表达式括起来

((a*b) + (c*d)) + e*f

        拆表达式

        将复杂的表达式拆分成多个简单的表达式

int a = 3;
--a;
a + a;

最后,感谢大家观看!

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值