入门学习计算机第十二天—操作符详解
发布日期:2021-06-28 16:38:45 浏览次数:2 分类:技术文章

本文共 6785 字,大约阅读时间需要 22 分钟。

入门学习计算机第十二天—操作符详解

编译器:Microsoft Visual Studio 2010

前言

记录第十一天学习C语言的博客。

1、 算术操作符

、+ 、 - 、*、/、%

1,除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。
2,对于/操作符,如果两个操作数都为整数,执行整数除法。而只要有浮点数(小数)执行的就是浮点数除法。
3,%操作符的两个操作数必须为整数,返回的是整除之后的余数

2、移位操作符

<< 左移操作符

` >>右移操作符
右操作符
1、算术右移:(基本都是算术右移)
右边丢弃,左边补原符号位
2、逻辑右移:
右边丢弃,左边补0

int main(){
int a = 16; int b = a>>1; //>> -- 右移操作符,移动的是二进制位 //00000000000000000000000000010000 // 00000000000000000000000000010000 //最高位补原符号位0 return 0;}

结果输出的是8,右移一位有除以2的效果。

当负数进行右移时:

int main(){
int a = -1; int b = a>>1; //>> -- 右移操作符,移动的是二进制位 // // //最高位补原符号位0 return 0;}

输出的结果是-1

整数的二进制表示有:原码,反码,补码

存储在内存中的是补码
-1的原码是10000000000000000000000000000001,最高位为符号位
(原码转化为反码,符号位不变,其他位按位取反)
-1的反码是11111111111111111111111111111110
(反码转化位补码,反码加一)
-1的补码是11111111111111111111111111111111
右移一位之后还是11111111111111111111111111111111(此时还是补码,需要转化为原码输出),所以输出的结果还是-1;

左移操作符

左边丢弃,右边补0

int main(){
int a = 10; int b = a << 1; //<<-- 左移操作符,移动的是二进制位 return 0;}

输出的结果是20。左移一位有乘以2的效果。

警告!!!!!:对于移位操作符,不要移动负数位,这个是标准未定义;

3、位操作符

位操作符:

&:按位与
|:按位或
^:按位异或
他们的操作数都是整数

&按位与: 有0则0

int main(){
int a = 3;//011 int b = 5;//101 int c = a&b//001 return 0;}

输出的结果是1

|按位或: 有1则1

int main(){
int a = 3;//011 int b = 5;//101 int c = a|b;//111 return 0;}

输出的结果是7

^按位异或: 对应的二进制位相同为0,相异为1

int main(){
int a = 3;//011 int b = 5;//101 int c = a^b;//110 return 0;}

输出的结果是6

一道变态的面试题:

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

第一种方法:加减法

int main(){
int a = 5; int b = 3; a= a+b;//a=8,b=3 b= a-b;//a=8,b=5 a = a-b;//a=3,b=5 return 0;}

这种方法有缺陷,当a和b的值非常大的时候,两个数相加有可能会溢出。

第二种方法:使用异或操作符

int main (){
int a = 5; int b = 3; a = a^b;//a为110,b为011。a = a^b为101 b = a^b;//a为101,b为011。b = a^b为110 a = a^b;//a为101,b为110。a = a^b为011}

题目二:

统计一个整数的二进制有多少个1

第一种解法:

int main(){
int num = 0; scanf("%d",&num); while(num) {
if(num % 2 ==1) count++; num = num /2;  } printf("%d\n", num); return 0;}

但此方法有个缺陷是,当值为负数时,会错误。

第二种解法:

int main(){
int num = 0; int count = 0; scanf("%d", &num); int i = 0; for(i=0; i<32; i++) {
if(1 ==((num>>i)&1)) count++; } return 0;}

这种方法可以运用于负数

第三种:

int main(){
int num = 0; int count = 0; scanf("%d", &num); while(num) {
count++; num = (num&(num-1)); } pirntf("%d\n",count);}

4、赋值操作符

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

int a = 10;int x = 0;int y = 20;a = x= y+1;//不推荐,建议分开写x =y+1;a = x;

复合赋值操作符

+=;-=;*=;/=;>>=;<<=;

5、单目操作符

!:逻辑反操作

真变成假,假变成真

int main(){
int a = 0; if(!a) {
printf("hehe\n") } return 0;}

± : 负值\正值

&:取地址操作符

int main(){
int a = 10; int* p = &a; //*p解引用操作符}

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

int main(){
int a =10; char c = 'r'; char* p = &c; int arr[10]= {
0}; printf("%d\n",sizeof(a));//4 printf("%d\n",sizeof(c));//1 printf("%d\n",sizeof(p));//4 printf("%d\n",sizeof(arr));//40 return 0;}
int main(){
short s = 0; int a = 10; printf("%d\n", sizeof(s= a+5));//2 printf("%d\n",s);// 0 s的值并没有改变 return 0;}

~:按(二进制)位取反

int main(){
int a = 0; //00000000000000000000000000000000 //11111111111111111111111111111111 -按位取反/补码 //11111111111111111111111111111110 -反码 //10000000000000000000000000000001 - 原码 printf("%d\n", ~a); return 0;}

输出的值就是-1

案例:

int main(){
int a = 15; //00000000000000000000000000001111 让1111变成1011 //11111111111111111111111111111011 按位与 但是这个数如何获得 //00000000000000000000000000000001 1<<2再取反即可 a = a & (~(1<<2)); printf("%d\n",a); return 0;}

– ++ :前置 /后置

int main(){
int a = 10; printf("%d\n",++a);//先++,后使用 打印结果是11 printf("%d\n",a++);//先使用,后++ 打印结果是10 return 0;}

*:间接访问操作符(解引用操作符)

(类型):强制转化类型操作符

int mian(){
int a = (int)3.14; return 0;}

6、关系操作符

<= >= != ==

赋值 = 和判断相等== 容易弄混

7、逻辑操作符

&&逻辑与 :

| |逻辑或 :关注数本身

区分逻辑与和按位与:

1&&2 ----->1
1&2-------->0

区分逻辑或与按位或:

1||2---------->1
1|2----------->3

360面试题:

int main(){
int i =0,a=0,b = 2 ,c = 3 ,d =4; i = a++ && ++b && d++; printf("a = %d\nb = %d\nc = %d\nd = %d\n",a,b,c,d); return 0;}

输出的结果是

在这里插入图片描述
a++&&++b,当左边是a++,先使用a,a=0,&&的结果就是0,为假,&&右边的值不管是什么表达式都不会再计算了。

int main(){
int i =0,a=0,b = 2 ,c = 3 ,d =4; i = a++ || ++b || d++; printf("a = %d\nb = %d\nc = %d\nd = %d\n",a,b,c,d); return 0;}

输出的结果为

在这里插入图片描述

a++||++b,当左边是a++,先使用a,a=0,||的结果就是0,为假,继续计算++b, 先++,后使用,b等于3,为真,||右边的值不管是什么表达式都不会再计算了。

8、条件操作符

exp1 ? exp2 : exp3

表达式1如果为真,执行表达式2,表达式2的结果为整个表达式的结果。如果为假,执行表达式3,表达式3的结果为整个表达式的结果

int main(){
int a = 0; int b = 0; if(a > 5) b = 3; else b = -3; //可以写成 b = (a > 5 ? 3 : -3);}

9、逗号表达式

exp1,exp2,exp3, … ,expN

从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

int main(){
int a = 1; int b = 2; int c = (a>b, a=b+10, a, b=a+1);//a>b不执行 print("%d\n",c) return 0; }

输出的结果是13

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

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

int arr[10];//创建数组arr[9] = 10;//实用下标引用操作符[ ]的两个操作数是arr和9

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

int get_max(int x , int y)//定义函数的语法规则{
return x > y ? x : y;}int main(){
int a =10; int b =20; int max = get_max(a,b);//函数调用操作符 printf("max = %d\n",max);}

访问一个结构的成员

结构体.成员名

结构体指针->成员名

struct Stu{
//成员变量 char name[20]; int age; char id[20];//创建一个结构体类型-struct Stu}; int main(){
//使用struct Stu 这个类型创建了一个学生对象s1,并初始化 struct Stu s1 ={
"张三",20,"2018024"}; // struct Stu* ps= &s1; printf("%s\n", s1.name); //printf("%s\n", ps->name); printf("%d\n", s1.age); printf("%s\n", s1.id); return 0;}

在这里插入图片描述

表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。

同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

隐式类型转换:

C的整型算术运算总是至少以缺省整型类型的精度进行的。
为了获得这个精度,表达式中的字符和短整型操作符在使用之前转换为普通整型,这种转换类型称为整型提升
如何进行整型提升?
整型提升是按照变量的数据类型的符号位来提升的,无符号类型,补0来提升

int main(){
char a =3; //00000000000000000000000000000011 因为a是char类型,char类型是1个字节 //00000011 - a char b = 127; //00000000000000000000000001111111 同理 //01111111 -b //a和b如何相加,整型提升,char是有符号 //a-00000000000000000000000000000011 //b-00000000000000000000000001111111 //c-00000000000000000000000010000010 //进行截断c-10000010 //进行整型提升 //11111111111111111111111110000010--补码 //11111111111111111111111110000001--反码 //10000000000000000000000001111110--原码 char c = a+b; printf("%d\n",c); return 0;}

输出的结果是-126

int main(){
char a = 0xb6;//1011 0110 short b = 0x600;// 0000 0000 int c = 0x6000000; if(a == 0xb6) printf("a"); if(b == 0x600) printf("b"); if(c == 0x6000000) printf("c"); return 0;}

只输出了c。

因为 char short 在进行判断(也算表达式运算)时,需要整型提升,一旦提升,值就不会再相等了。

int main(){
char c = 1; printf("%u\n",sizeof(c)); printf("%u\n",sizeof(+c)); printf("%u\n",sizeof(!c)); return 0;}

输出的结果为

1
4
1
只要参与表达式运算,就会发生整型提升,表达式+c,就会发生提升,所以sizeof(+c)是4个字节

算术转换

如果某个操作符的各个操作数属于不同类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。

long double

double
float
unsigned long int
long int
unsigned int
int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

操作符的属性

复杂表达式的求值有三个影响的因素:

1、操作符的优先级
2、操作符的结合性
3、是否控制求值顺序
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。


计算机知识/代码知识(零碎)

在Window系统下,win+r输入calc可以打开计算器。

转载地址:https://blog.csdn.net/xiaotangyu7dong/article/details/115716721 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:入门学习计算机第十三天—初识指针
下一篇:用数组写三子棋游戏

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月13日 14时52分46秒