C语言---操作符详解(1)https://developer.aliyun.com/article/1544300
5.位操作符:&、|、^、~
& 按位与
| 按位或
^ 按位异或
~ 按位取反
操作数必须是整数
这里的位都是二进制位,只关注与二进制的计算
以下两种操作符只关注真假
&&逻辑与
||逻辑或
int main() { int a = 6; //00000000000000000000000000000110---6的补码 int b = -7; //10000000000000000000000000000111-- -7的原码 //11111111111111111111111111111000-- -7的反码 //11111111111111111111111111111001-- -7的补码 int c = a & b;//a和b的补码的二进制位进行运算 //对应的二进制位,有0则为0,两个同时为1才为1 //00000000000000000000000000000110---6的补码 //11111111111111111111111111111001-- -7的补码 //00000000000000000000000000000000 printf("c=%d\n", c);//c=0 return 0; } //对应的二进制位,有0则为0,两个同时为1才为1
int main() { int a = 6; //00000000000000000000000000000110---6的补码 int b = -7; //10000000000000000000000000000111-- -7的原码 //11111111111111111111111111111000-- -7的反码 //11111111111111111111111111111001-- -7的补码 int c = a | b;//a和b的补码的二进制位进行运算 //规则:只要有1就是1,两个同时为0才为0 //00000000000000000000000000000110---6的补码 //11111111111111111111111111111001-- -7的补码 //11111111111111111111111111111111----运算出的补码 //10000000000000000000000000000000---取反 //10000000000000000000000000000001 +1--转换出的原码 printf("c=%d\n", c);//c=-1 return 0; } 规则:只要有1就是1,两个同时为0才为0
int main() { int a = 6; //00000000000000000000000000000110---6的补码 int b = -7; //10000000000000000000000000000111-- -7的原码 //11111111111111111111111111111000-- -7的反码 //11111111111111111111111111111001-- -7的补码 int c = a ^ b;//a和b的补码的二进制位进行运算 //规则:对应的二进制位上,相同为0,相异为1 //00000000000000000000000000000110---6的补码 //11111111111111111111111111111001-- -7的补码 //11111111111111111111111111111111----运算出的补码 //10000000000000000000000000000000---取反 //10000000000000000000000000000001 +1--原码 printf("c=%d\n", c);//c=-1 return 0; } 对应的二进制位上,相同为0,相异为1 //不让创建临时变量(第三个变量),实现两个整数的交换 int main() { int a = 3; int b = 5; printf("交换前:a=%d b=%d\n", a, b); //不存在溢出现象 a= a ^ b;//111 b= a ^ b;///222//a ^ b^ b=a 将111中a 的值带到222中 a= a ^ b;///333//a ^ b^a=b 将222中b的值带到333中 printf("交换后:a=%d b=%d\n", a, b); return 0; } 011--a 101--b 110---a ^ b =a 011---a ^ b ^ b=b 101---a ^ b //3^3=0 //a^a=0 //0^a=a /* * 异或是支持交换的 3^3^5=5 3^5^3=5 */ //另外一种写法 //不让创建临时变量(第三个变量),实现两个整数的交换 int main() { int a = 3; int b = 5; int c = 0; printf("交换前:a=%d b=%d\n", a, b); //不存在溢出现象 c = a; a = b; b = c; printf("交换后:a=%d b=%d\n", a, b); return 0; }
int main() { int a = 0; printf("%d\n", ~a);/*结果为 - 1*/ //~是按(二进制)位取反 //00000000000000000000000000000000---0的补码 //11111111111111111111111111111111--- //10000000000000000000000000000000 //10000000000000000000000000000001--最后的补码 return 0; }
^: 异或操作可以直接比较两个整数的对应位。当两个整数的对应位相同时,异或结果为0;当对应位不同时,结果为1。这意味着异或结果的每一位都直接告诉我们原始两个整数在该位上是否不同。
6.单目操作符
& -- 取地址操作符
- -- 解引用操作符
如果写的是a&b,---&的意思就是按位与
但如果int a=10;--&a就是取a的地址
双目操作符的时候就是按位与
单目操作符的时候就是取地址
单目操作符有这些:
!
++
--
&
+
-
~
sizeof
(类型)
7.逗号表达式
exp1,exp2,exp3,exp4
逗号表达式就是用逗号隔开的表达式
逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果
int main() { int a = 1; int b = 2; //逗号表达式 //逗号表达式要从左依次向右计算 //因为前面表达式的计算可能会影响后面的计算 int c = (a > b, a = b + 10, a, b = a + 1); printf("%d", c);//输出结果是13 return 0; }
8.下标访问[]、函数调用()
int main() { int arr[10] = { 1,2,3,4,5 }; int m =arr[4];//数组中下标是4的元素 //[] 下标引用操作符--操作数是:arr,4---数组名和下标 printf("%d", m);//输出结果是5 return 0; }
int Add(int x, int y) { return x + y; } int main() { printf("hehe\n");//这里的()就是函数调用操作符 //操作数是:一个是函数名,一个是穿过去的字符串 printf("%d\n", 100);//这里的操作数:双引号内的字符串 //函数名 还有100 int ret = Add(3, 5);//Add,3,5就是这个函数调用 //操作符的操作数 //函数调用操作符,最少有几个操作数? //至少有一个操作数,就是函数名 return 0; }
9.结构成员访问操作符
结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量,如:标量、数组、指针、甚至是其他的结构体
结构体的关键字叫struct---
//学生类型 struct Student { //成员变量 char name[20];//名字 int age;//年龄 float score;//成绩 }a4, a5, a6;//也是全局变量 struct Student a3 = {"王",25,68.5};//全局变量 struct point { int x; int y; }; struct S { char ch; struct point p; int arr[10]; double d; }; int main() { struct Student a1 = {"翠花",20, 98.0};//用结构体类型创造结构体变量 struct Student a2 = {"旺财",18,69.8};//局部变量 struct S s = { 'a',{4,5},{1,2,3,4,5,6,7},3.14 }; printf("%c", s.ch); printf("坐标是:%d %d\n", s.p.x, s.p.y); printf("%d\n", s.arr[0]); printf("%lf\n", s.d); return 0; } //通过结构体的名字加.去查找你存放的数据 //操作符左边是结构体变量.结构体成员名 //如果向往里面输入数据,就将pritnf改成scanf输入数据就行了
10.操作符的属性:优先级、结合性
c语言的操作符有两个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序
int main() { int r = 3 + 4 * 5;//先算乘法,再算加法 return 0; }
优先级
一个表达式包含多个运算符,哪个运算符应该优先执行,各种运算符的优先级是不一样的
当我们明确了优先级和结合性那我们是否能确定一个表达式的计算结果呢?
11.表达式求值
为了获取精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升
char 是否是signed char?
不一定,是取决于编译器的
vs上,char == signed char
char类型的取值范围是-128~127
算术转换
整型提升讨论的是表达式中char和short类型的值
算术转换讨论的是大于等于整型类型的其他类型
1.long double
2.double
3.float
4.unsigned long int
5.long int
6.unsigned int
7.int
从下向上转换--两种不同类型相加,较低档次的会被很转化为较高档次的
double a=10;
int b =10;
a+b的计算中,a会被转化成和b类型一样的double 类型
即是有操作符的优先级和结核性,我们写出的表达式仍然存在潜在风险的,建议不必要写复杂的表达式