1.算术操作符:
+ - * / %
1. 除了% 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于/ 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
2.移位操作符
<< 左移操作符:
左边抛弃、右边补0
>> 右移操作符:
1. 逻辑移位
左边用0填充,右边丢弃
2. 算术移位(一般采用)
左边用原该值的符号位填充,右边丢弃
3. 位操作符
& //按位与 (0&1=0)
| //按位或 (0|1=1)
^ //按位异或 (对应二进制位相同为0,相异为1)
注:他们的操作数必须是整数。
例:交换a和b的值,不引入第三个变量
1 #include <stdio.h>//交换a和b的值 2 int main() 3 { 4 int a = 3; 5 int b = 5; 6 a = a ^ b; 7 b = a ^ b;//b=a^b^b=a 8 a = a ^ b;//a=(a^b)^(a^b^b)=a^b^a=a^a^b=b,满足交换律 9 printf("a = %d, b = %d", a, b); 10 return 0; 11 }
4. 赋值操作符
+=
-=
*=
/=
%=
>>=
<<=
&=
|=
^=
5. 单目操作符
单目操作符不改变数值
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 分为前置、后置
++ 分为前置、后置
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
#include <stdio.h> int main() { int a = 13; ////把a的二进制中的第5位置成1 a = a | (1 << 4);//0|1 = 1 printf("a = %d\n",a);//29 //a = 00...001101 //1<<4 = 00...010000 //a|(1<<4)= 00...011101 //把a的二进制中的第5位置成0 a = a & ~(1 << 4);//0&1 = 0, ~为单目操作符:按位取反 printf("a = %d\n", a);//13 //a = 00...001101 //1<<4 = 00...010000 //~(1<<4) = 11...101111 //a&~(1 << 4) = 00...001101 return 0; }
++和--的前置与后置:
#include <stdio.h> int main() { int a = 10; printf("%d\n", a--);//10,a--为先使用后做减法 printf("%d\n", a);//9 return 0; }
sizeof:
1 #include <stdio.h> 2 void test1(int arr[]) 3 { 4 printf("%d\n", sizeof(arr));//(5) 5 } 6 void test2(char ch[]) 7 { 8 printf("%d\n", sizeof(ch));//(6) 9 } 10 int main() 11 { 12 short s = 5; 13 int a = 10; 14 printf("%d\n", sizeof(s = a + 2));//(1) 15 printf("%d\n", s);//(2) 16 17 int arr[10] = { 0 }; 18 char ch[10] = { 0 }; 19 printf("%d\n", sizeof(arr));//(3) 20 printf("%d\n", sizeof(ch));//(4) 21 test1(arr); 22 test2(ch); 23 return 0; 24 }
(1) 值为2,即short的尺寸。
(2) 值为s原本的值5,因为sizeof不改变值
(3)和(4)分别为40和10
(5)和(6)都为数组第一个元素的地址大小,即指针大小,为4或8
6. 关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
7.逻辑操作符
&& 逻辑与
|| 逻辑或
1 #include <stdio.h> 2 int main() 3 { 4 int i = 0,a=0,b=2,c =3,d=4; 5 i = a++ && ++b && d++; //注释掉此行,结果为多少? 6 i = a++||++b||d++; //注释掉此行,结果又为多少? 7 printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d); 8 return 0; 9 }
注释掉第5行,在逻辑或中,a++判定为0,++b判定为3,即停止第6行的运算。在逻辑或运算中,有1即停止运算输出为1,此时打印结果为1 3 3 4,因为d没有运算
注释掉第6行,在逻辑与中,a++判定为0,即停止第5行的运算。在逻辑与运算中,有0即停止运算输出为0,此时打印结果为1 2 3 4, bcd都没有参与运算
8.条件操作符
exp1 ? exp2 : exp3
exp1为真,则只计算exp2;若exp1为假,则只计算exp3
9.逗号表达式
exp1, exp2, ... ,expN
从左到右依次运算,但是整个表达式的结果是最后一个表达式的结果
10. 下标引用、函数调用和结构成员
1. [ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
2. ( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
1 #include <stdio.h> 2 void test1() 3 { 4 printf("hehe\n"); 5 } 6 void test2(const char *str) 7 { 8 printf("%s\n", str); 9 } 10 int main() 11 { 12 test1(); //()作为函数调用操作符。 13 test2("hello bit.");//()作为函数调用操作符。 14 return 0; 15 }
3. 访问一个结构的成员
. 结构体 . 成员名
-> 结构体指针 -> 成员名
1 #include <stdio.h> 2 struct Stu 3 { 4 char name[10]; 5 int age; 6 char sex[5]; 7 double score; 8 }; 9 10 void set_age1(struct Stu stu) 11 { 12 stu.age = 18; 13 } 14 void set_age2(struct Stu* pStu) 15 { 16 pStu->age = 18;//结构成员访问 17 } 18 int main() 19 { 20 struct Stu stu; 21 struct Stu* pStu = &stu;//结构成员访问 22 stu.age = 20;//结构成员访问 23 set_age1(stu); 24 pStu->age = 20;//结构成员访问 25 set_age2(pStu); 26 return 0; 27 }
11. 表达式求值
隐式类型转换:C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU (general-purpose CPU) 是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。
算术转换:
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
操作符的属性:
复杂表达式的求值有三个影响的因素。
1. 操作符的优先级
2. 操作符的结合性
3. 是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。
总结:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的
标签:2308,操作数,10,int,++,操作符,printf From: https://www.cnblogs.com/scut4787749233/p/17674249.html