本文共 6785 字,大约阅读时间需要 22 分钟。
入门学习计算机第十二天—操作符详解
编译器:Microsoft Visual Studio 2010
前言
记录第十一天学习C语言的博客。
1、 算术操作符
、+ 、 - 、*、/、%
1,除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。 2,对于/操作符,如果两个操作数都为整数,执行整数除法。而只要有浮点数(小数)执行的就是浮点数除法。 3,%操作符的两个操作数必须为整数,返回的是整除之后的余数2、移位操作符
<< 左移操作符
` >>右移操作符 右操作符: 1、算术右移:(基本都是算术右移) 右边丢弃,左边补原符号位 2、逻辑右移: 右边丢弃,左边补0int 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;左移操作符:
左边丢弃,右边补0int 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----------->3360面试题:
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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!