大家好我是Cbiltps,在我的博客中如果有难以理解的句意,难以用文字表达的重点,我会有配图。所以我的博客配图非常重要!!!
如果你对我感兴趣请看我的第一篇博客!
算数操作符有:
+ - * / %
除了%
操作符之外,其他的几个操作符可以作用于整数和浮点数。
/
操作符#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
,为什么呢?
因为操作数中有浮点数,才执行浮点数除法。
%
操作符%
操作符是取模操作符,也叫取余操作符。
int ret4 = 10 % 4;printf("%d", ret4);//打印出来是2
注意:%
操作符只能针对整形类型
<< 左移操作符>> 右移操作符
<<
左移操作符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
关于原码、反码、补码,请大家看我写的另一篇进阶博客!
>>
左移操作符移位规则:
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
位操作符有:
&
按位与|
按位或^
按位异或注:他们的操作数必须是整数。
&
按位与操作符计算规则:
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
|
按位或操作符计算规则: 二进制位只要有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
^
按位异或操作符计算规则: 二进制位相同为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;}
思路图解:
注意:这样写代码的可读性不够好,而且只适用于整型
赋值操作符可以让你得到一个你之前不满意的值,也就是你可以给自己重新赋值。
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;//复合赋值
单目操作符就是只有一个操作数的操作符
!
逻辑反操作
-
负值
+
正值
&
取地址
&arr[0];//数组首元素的地址&arr[9];//取出的是第10个元素的地址&arr;//取出数组的地址
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;
我们来看一个题,看它们分别输出的是多少:
#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;}
输出结果:
更多关于数组的知识请看我的上一篇博客!
关系操作符在同类之间比较才有意义!
>
>=
<
<=
!=
用于测试“不相等”==
用于测试“相等”这些关系运算符比较简单,没什么可讲的,但是我们要注意一些运算符使用时候的陷阱。
注意:在编程的时候 =
和 ==
写错,会导致出错!
&&
逻辑与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;}
思路图解:
条件操作符也叫三目操作符
exp1 ? exp2 : exp3
int a = 0;int b = 0;if (a > 5) b = 3;else b = -3; //这里有更简单的写法:(a > 5) ? (b = 3) : (b = -3);//直接搞定
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){ //业务处理}
[ ]
下标引用操作符
操作数:一个数组名 + 一个索引值
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;}
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
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数据可视化大佬☀️《❤️记得收藏❤️》 目录 ?️?开讲啦!!!!?️?苏州程序大白?️??博主介绍前言数据关系可视化散点图 Scatter plots折线图强调连续性 Emphasizing continuity with line plots同时显示多了图表 数据种类的可视化 Plotting with categorical da...
目录 一、什么是C语言? 二、第一个C语言程序 代码 程序分析 程序运行 一个工程中出现两个及以上的main函数 代码 运行结果 分析 三、数据类型 数据各种类型 为什么会有这么多的数据类型? 计算机单位 各个数据类型的大小 注意事项 数据类型的使用 四、变量和常量 变量的分类 变量的使用 变量的作用域和生命周期 常量 五、字符串+转义字符+注释 字符串 转义字符 注释 六、选择语句 ...
☀️苏州程序大白一文教你学会微信小程序开发☀️《❤️记得收藏❤️》 目录 ?️?开讲啦!!!!?️?苏州程序大白?️??博主介绍?前言?讲讲专享小程序有什么优势? ?小程序文件分析?事件绑定?图片问题?轮播图swiper?自定义组件?生命周期?页面生命周期?项目制作?缓冲事件?`es7 async`语法 ?触底事件❄️下拉刷新页面❄️css省略号❄️预览大图❄️购物车模拟❄️获取地...
阅读 944·2023-04-25 15:42
阅读 3563·2021-11-02 14:38
阅读 2872·2021-09-30 09:48
阅读 1391·2021-09-23 11:22
阅读 3361·2021-09-06 15:02
阅读 3173·2021-09-04 16:41
阅读 589·2021-09-02 15:41
阅读 1992·2021-08-26 14:13