资讯专栏INFORMATION COLUMN

【C语言初阶】❤️ 教你使用C语言中的各种操作符(熟练运用+必须收藏)❤️

source / 3360人阅读

温馨提示

大家好我是Cbiltps,在我的博客中如果有难以理解的句意难以用文字表达的重点,我会有配图。所以我的博客配图非常重要!!!

如果你对我感兴趣请看我的第一篇博客

本章重点

  1. 各种操作符的介绍。
  2. 表达式求值

正文开始


1. 操作符分类


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

2.算数操作符


算数操作符有:+ - * / %
除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。

2.1 /操作符

#include int main(){	int ret = 9 / 2;//对于 /(除号) 两边都是整数,执行的整数除法	double ret2 = 9 / 2;//它的值是什么?	double ret3 = 9 / 2.0;//它的值是什么?	printf("%d/n", ret);	printf("%lf/n", ret2);	printf("%lf/n", ret3);	return 0;}

运行结果如下:

第二个结果还是4.0,为什么呢?
因为操作数中有浮点数,才执行浮点数除法。

2.2 %操作符

%操作符是取模操作符,也叫取余操作符

int ret4 = 10 % 4;printf("%d", ret4);//打印出来是2

注意:%操作符只能针对整形类型


3. 位移操作符


<< 左移操作符>> 右移操作符

3.1 <<左移操作符

int a = 5;int b = a << 1;printf("%d/n", b);//打印出来的是 10    //要看懂下面的图解,要明白一些知识点:        //移位操作符,移动的是二进制位	//对于整数的二进制有3中表示形式:原码、反码、补码		//正整数 - 原码、反码、补码相同	//负整数		//原码 - 直接按照数字的正负写出的二进制序列	//反码 - 原码的符号位不变,其他位按位取法得到的	//补码 - 反码+1		//整数 在内存中存储的是二进制的补码


如果是一个负数的话,看代码:

int c = -1;int d = c << 1;printf("%d/n", d);//打印的是原码的值,打印出来是 -2	//10000000000000000000000000000001 - 原码	//11111111111111111111111111111110 - 反码	//11111111111111111111111111111111 - 补码


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

关于原码、反码、补码,请大家看我写的另一篇进阶博客

3.2 >>左移操作符

移位规则:
1. 逻辑移位:左边用0填充,右边丢弃
2. 算术移位:左边用原该值的符号位填充,右边丢弃

举例:

int a = 5;int b = a >> 1;printf("%d/n", b);//打印出来的是 2


再用负数举个例子:

int c = -1;int d = c << 1;printf("%d/n", d);//打印出来还是 -1


在这里是补了原来的符号位,所以 VS2019 采用算术右移!

警告⚠ :
1:对于移位运算符,不要移动负数位,这个是标准未定义的。
2:不管是被移动数还是移动的位数都必须是整数。

例如(错误演示):

int num = 10;num>>-1;//error

4. 位操作符


位操作符有:

  • & 按位与
  • | 按位或
  • ^ 按位异或

注:他们的操作数必须是整数。

4.1 &按位与操作符

计算规则:
1:二进制位上只要有0,那就是0
2:二进制位上两个同时为1,那就是1

	int a = 3;	int b = -2;	int c = a & b;	printf("%d/n", c);//打印出来是 2		//%d - 说明我们要打印c的值,以有符号的形式		//00000000000000000000000000000011 -3的原码	//11111111111111111111111111111110 -2的补码	//00000000000000000000000000000010 这个数是2

4.2 |按位或操作符

计算规则: 二进制位只要有1,就为1

int a = 3;int b = -2;int c = a | b;printf("%d/n", c);//打印 -1	//00000000000000000000000000000011 -3的原码	//11111111111111111111111111111110 -2的补码	//11111111111111111111111111111111	//11111111111111111111111111111111 补码	//11111111111111111111111111111110 反码	//10000000000000000000000000000001 原码 它的值是-1

4.3 ^按位异或操作符

计算规则: 二进制位相同为0,相异为1

int a = 3;int b = -2;int c = a ^ b;//打印出来是 -3printf("%d/n", c);	//00000000000000000000000000000011 -3的原码	//11111111111111111111111111111110 -2的补码	//11111111111111111111111111111101	//11111111111111111111111111111101 补码	//11111111111111111111111111111100 反码	//10000000000000000000000000000011 原码 它的值是-3

一道{{BANNED}}的面试题:

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

#include int main(){	int a = 3;	int b = 5;	printf("交换前:a=%d b=%d/n", a, b);	a = a ^ b;	b = a ^ b;	a = a ^ b;	printf("交换后:a=%d b=%d/n", a, b);	return 0;}

思路图解:

注意:这样写代码的可读性不够好,而且只适用于整型


5. 赋值操作符


赋值操作符可以让你得到一个你之前不满意的值,也就是你可以给自己重新赋值

int weight = 120;//体重weight = 89;//不满意就赋值double salary = 10000.0;salary = 20000.0;//使用赋值操作符赋值

赋值操作符可以连续使用,比如:

int a = 10;int x = 0;int y = 20;a = x = y + 1;//连续赋值

这样的代码感觉怎么样?

那这样写:

x = y + 1;a = x;

更加清晰爽朗而且易于调试

复合赋值符:

  • +=
  • -=
  • *=
  • /=
  • %=
  • <<=
  • &=
  • |=
  • ^=

这些运算符都可以写成复合的效果,比如:

int x = 10;x = x + 10;x += 10;//复合赋值

6. 单目操作符


单目操作符就是只有一个操作数的操作符

6.1 各种单目操作符

! 逻辑反操作

- 负值

+ 正值

& 取地址

&arr[0];//数组首元素的地址&arr[9];//取出的是第10个元素的地址&arr;//取出数组的地址

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

  • sizeof是操作符,不是函数
  • sizeof是计算变量或者类型创建变量的内存大小(单位:字节),单位是和内存中存放什么数据没有关系
//以下几种写法都是一样的printf("%d/n", sizeof(a));//4printf("%d/n", sizeof a);//4printf("%d/n", sizeof(int));//4
//这里有一个问题;int a = 5;short s = 10;printf("%d/n", sizeof(s = a + 2));//打印出来是 2printf("%d/n", s);  //打印出来是 10  因为:sizeof 内部的表达式不参与运算

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

  • 包括符号位也可以按位取反
#incluide <stdio.h>int main(){	int a = 0;	//00000000000000000000000000000000	int b = ~a;	printf("%d/n", b);	//00000000000000000000000000000000	//11111111111111111111111111111111 所有位按位取反	// 	//11111111111111111111111111111110 反码	//10000000000000000000000000000001 原码	//-1	return 0;}

-- 前置、后置--

  • 前置- -:先- -,后使用
int a = 10;int b = a--;printf("%d/n", b);//这里打印出来还是 10
  • 后置- -:先使用,后- -
int a = 10;int b = --a;printf("%d/n", b);//这里打印出来才是9

++ 前置、后置++

  • 前置++:先++,后使用
  • 后置++:先使用,后++

千万注意:不要这样子写代码(垃圾代码),会被公司开除的!

int main(){	int a = 1;	int b = (++a) + (++a) + (++a);//err	printf("b=%d/n", b);	return 0;}

这里两个编译器下不一样!

* 间接访问操作符(解引用操作符),可以和& 取地址搭配使用

(类型) 强制类型转换

int a = (int)3.14;//默认写出的浮点数是double的,所以可以强制转换printf("%d/n", a);return 0;

6.2 sizeof 和 数组

我们来看一个题,看它们分别输出的是多少:

#include void test1(int arr[])//它的本质数是(int* arr[]){	printf("%d/n", sizeof(arr));//传的是首元素的地址}void test2(char ch[]){	printf("%d/n", sizeof(ch));//(4)}int main(){	int arr[10] = { 0 };	char ch[10] = { 0 };		printf("%d/n", sizeof(arr));//数组名多带带放在sizeof内部,数组名表示整个数组	printf("%d/n", sizeof(ch));//(3)	test1(arr);	test2(ch);	return 0;}

输出结果:

更多关于数组的知识请看我的上一篇博客


7. 关系操作符(后面的操作符不多带带出现在目录中)


关系操作符在同类之间比较才有意义!

  • >
  • >=
  • <
  • <=
  • != 用于测试“不相等”
  • == 用于测试“相等”

这些关系运算符比较简单,没什么可讲的,但是我们要注意一些运算符使用时候的陷阱。
注意:在编程的时候 === 写错,会导致出错!


8. 逻辑操作符


  • && 逻辑与
    一假必假:
int a = 0;int b = 3;int c = a && b;//只判断真假,所以打印出来是 0
  • || 逻辑或
    一真必真:
int a = 0;int b = 3;int c = a || b;printf("%d/n", c);//打印出来是 1

来看一道 360 的笔试题:

#include int main(){	int i = 0, a = 0, b = 2, c = 3, d = 4;	i = a++ && ++b && d++;	//i = a++||++b||d++;	printf(" a = %d /n b = %d /n c = %d /nd = %d/n", a, b, c, d);//打印出来的是1 2 3 4		return 0;}

思路图解:

那如果是逻辑或的话:

#include int main(){	int i = 0, a = 0, b = 2, c = 3, d = 4;	i = a++ || ++b || d++;	printf(" a = %d/n b = %d /n c = %d/n d = %d/n", a, b, c, d);//打印错来的是1 3 3 4		return 0;}

思路图解:


9. 条件操作符


条件操作符也叫三目操作符

exp1 ? exp2 : exp3

int a = 0;int b = 0;if (a > 5)	b = 3;else	b = -3;	//这里有更简单的写法:(a > 5) ? (b = 3) : (b = -3);//直接搞定

10. 逗号表达式


exp1, exp2, exp3, …expN

逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式规则:从左向右依次执行,整个表达式的结果是最后一个表达式的结果

代码演示:

//代码1int a = 1;int b = 2;int c = (a>b, a=b+10, a, b=a+1);//c是多少?看的是最后一个表达式//代码2if (a =b + 1, c=a / 2, d > 0)//最后一个表达式判断的是 d > 0
//代码3a = get_val();count_val(a);while (a > 0)//注意;这样写非常的冗余{	//业务处理	a = get_val();	count_val(a);}//如果使用逗号表达式,改写:while (a = get_val(), count_val(a), a > 0){    //业务处理}

11. 下标引用、函数调用和结构成员


[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值

int arr[10];//创建数组arr[9] = 10;//实用下标引用操作符。//[ ]的两个操作数是arr和9。
//下面表达的意思都是相同的 arr[4] -- > *(arr+4) --> *(4+arr) --> 4[arr]

( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

void test(){	printf("hehe/n");}int main(){	test();//这里就是函数调用操作符	return 0;}

结构成员访问操作符

  • . 结构变量.成员名
  • -> 结构体指针->成员名
#include struct Book{	char name[20];	float price;	char id[10];};void print1(struct Book b){	printf("书名: %s/n", b.name);//在这里访问结构体成员	printf("价格: %f/n", b.price);	printf("书号: %s/n", b.id);	//*(b.name);}void print2(struct Book* pb){	/*printf("书名: %s/n", (*pb).name);	printf("价格: %f/n", (*pb).price);	printf("书号: %s/n", (*pb).id);*/	printf("书名: %s/n", pb->name);//也可以这样访问	printf("价格: %f/n", pb->price);	printf("书号: %s/n", pb->id);}int main(){	struct Book b = {"C语言程序设计", 55.5f, "C20190201"};	print2(&b);	//print1(b);	//结构成员访问操作符	//结构变量.成员名	//结构体指针->成员名	//(*结构体指针).成员名	return 0;}

12. 表达式求值


表达式求值的顺序一部分是由操作符的优先级结合性决定
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型

12.1 隐式类型转换

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

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

整型提升的意义:

表达式的整型运算要在 CPU 的相应运算器件内执行,CPU 内整型运算器 (ALU) 的操作数的字节长度
一般就是 int 的字节长度,同时也是 CPU 的通用寄存器的长度。

因此,即使两个 char 类型的相加,在 CPU 执行时实际上也要先转换为 CPU 内整型操作数的标准长
度。

通用 CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令
中可能有这种字节相加指令)。所以,表达式中各种长度可能小于 int 长度的整型值,都必须先转
换为 int 或 unsigned int,然后才能送入 CPU 去执行运算。

如何进行整体提升呢?
整形提升是按照变量的数据类型的符号位来提升的

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

注意:无符号整形提升,高位补0

//举例:#include int main(){	char a = 3;//a是1byte - 8bit	//00000000000000000000000000000011	//00000011 - a	
                 
               
              

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/119290.html

相关文章

  • 苏州程序大白一文从基础手把手教你Python数据可视化大佬☀《❤记得收藏

    ☀️苏州程序大白一文从基础手把手教你Python数据可视化大佬☀️《❤️记得收藏❤️》 目录 ?️‍?开讲啦!!!!?️‍?苏州程序大白?️‍??博主介绍前言数据关系可视化散点图 Scatter plots折线图强调连续性 Emphasizing continuity with line plots同时显示多了图表 数据种类的可视化 Plotting with categorical da...

    Drinkey 评论0 收藏0
  • 整理2万字带你走进C语言(详细讲解+代码演示+图解)❤(强烈建议收藏!!!)

    目录 一、什么是C语言? 二、第一个C语言程序 代码 程序分析  程序运行 一个工程中出现两个及以上的main函数 代码 运行结果 分析 三、数据类型 数据各种类型 为什么会有这么多的数据类型? 计算机单位  各个数据类型的大小  注意事项 数据类型的使用 四、变量和常量 变量的分类 变量的使用 变量的作用域和生命周期  常量 五、字符串+转义字符+注释 字符串  转义字符 注释 六、选择语句  ...

    邱勇 评论0 收藏0
  • 苏州程序大白一文教你学会微信小程序开发☀《❤记得收藏

    ☀️苏州程序大白一文教你学会微信小程序开发☀️《❤️记得收藏❤️》 目录 ?️‍?开讲啦!!!!?️‍?苏州程序大白?️‍??博主介绍?前言?讲讲专享小程序有什么优势? ?小程序文件分析?事件绑定?图片问题?轮播图swiper?自定义组件?生命周期?页面生命周期?项目制作?缓冲事件?`es7 async`语法 ?触底事件❄️下拉刷新页面❄️css省略号❄️预览大图❄️购物车模拟❄️获取地...

    刘明 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<