1.算术操作符
/ 整型的除法 1/2--->0 出不开得到商
浮点型除法 1.0/2--->0.5 保证至少有一个小数
% 计算整除之后的余数 %操作符两端必须是整数
*若要另一个数的范围在0-8之间,应该改%9
2.移位操作符(移动的是二进制位,只针对整数)
整数在内存中存的是补码0
<<左移 左边丢弃,右边补零
>> 右移 算术移位 右边丢弃,左边补原符号位
逻辑移位 右边丢弃,左边补零
3.位操作符
| 按位(二进制)或
a 100101
b 110110
结果 110111 有1就为1,同时为0才为0
& 按位(二进制)与
a 100101
b 110110
结果 100101 有一个0即为零,两个1才为1
^ 按位(二进制)异或
a 100101
b 110110
结果 010011 相同为0,不相同为1
两个相同的数异或为0;一个数与0异或等于他自己
练习1.不创建变量(第三个变量)实现两数的交换
int main()
{
int a = 3;
int b = 5;
printf("交换前%d %d\n",a,b);
/*a = a + b;
b = a - b;
a = a - b;
会有溢出问题*/
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("交换后%d %d", a, b);
return 0;
}
练习2.求一个整数存储在内存中的二进制中1的个数
int main()
{
int a = 7;
int b = 1;
int count = 32;
int n = 0;
while (count)
{
if (a & b == 1)
{
n++;
}
a=a >> 1;
count--;
}
printf("%d",n);
return 0;
}
练习3.按位与、或、异或、取反用法
a=00000000000000000000000000000010 1左移两位
b=11111111111111111111111111111101 上面取反
c=00000000000000000000000000001100 要把第二位改成1 d=a|c
d=00000000000000000000000000001110
d=00000000000000000000000000001110 把第二位的1去掉 d&c
4.赋值操作符
= 可以连续赋值 a=x=y+1;(不建议这么写)
复合赋值符
+= -= *= /= %= >>= <<= &= |= ^=
5.单目操作符(只有一个操作数)
! 逻辑反操作 a=0 a为假 !a为真
- 负
+ 正
& 取地址(地址用%p打印) int*p=&a p是指针变量
sizeof 求所占内存空间大小,单位是字节
~ 对一个数的二进制位按位取反
-- 前置 、后置
++ 前置 、后置
int a=3
int b=++a //相当于a=a+1,b=a
结果:a=4 b=4
int a=3
int b=a++ //相当于b=a,a=a+1
结果:a=4 c=3
int a=10
printf("%d",a--) 结果为10
int a=3
int b=--a
结果:a=2,b=2
int a=3
int b=a--
结果:a=2,b=3
* 解引用操作符、间接访问操作符 int * p=&a *p解读地址找到a
int*是变量类型,p是变量名
(类型) 强制类型转换 int a=(int)3.14; srand((unsigned int)time(NULL));
指针大小都是四个字节,字符大小是一个字节
两个字符串是否相等用库函数 strcmp
6.关系操作符
> >= < <= == !=
7.逻辑操作符
&& 逻辑与 只关注真假
|| 逻辑或
练习
#include <stdio.h>
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\n d =%d\n",a, b,c, d);
return 0;
}
&&左边为假后面不算
||左边为真后面不算
结果a=1 b=2 c=3 d=4
8.条件操作符(三目操作符)
表达式1?表达式2:表达式3
真 √ ×
假 × √
求两个数较大的 int max=a>b?a:b;
9.逗号表达式
exp1,exp2,。。。。结果为最后一个表达式结果
10.下标引用、 函数调用、结构成员
[ ] arr[7]=7[arr] arr[7]=*(arr+7)跳过七个元素
() 操作数 函数名、参数
.和--> 结构成员
struct stu
{
char name[20];
int age;
double score;
};
void set_stu(struct stu *ps)
{
//strcpy((*ps).name, "zhansgan");
//(*ps).age = 20;
//(*ps).score = 100.0;
strcpy(ps->name,"zhangsan");
ps->age=20;
ps->score = 100.0;
}
void print_stu(struct stu ss)
{
printf("%s %d %1f\n", ss.name, ss.age, ss.score);
}
int main()
{
struct stu s = {0};
set_stu(&s);
print_stu(s);
return 0;
}
11.表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
11.1隐式类型转换(大小小于整形)
C的整型算术运算总是至少以缺省整型类型的精度来进行的,为了获得这个精度,表达式中的字符和短整型操作致在使用之前被转换为普通整型,这种转换称为整提升。
整型提升的意义
表达式的整形运算要在CPU的相应运算器件内执行,CPU内整型运算(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也变先转换为CPU内整型操作教的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int线unsigned Int,然后才能送入CPU去执行运算。
如何进行整形提升
按照变量的数据类型 的符号位来提升的
负数整形的提升
char c1=-1;
变量c1的二进制位(补码)中只有8的比特位(一个字节)
所以c1补码:11111111
整形提升时 高位补充符号位即为1
提升之后结果为
11111111111111111111111111111111
整数的整型提升
char c2=1;
00000001
00000000000000000000000000000001
无符号补0
截断
int main()
{
char a=5;
00000000000000000000000000000101
00000101-a
char b=126;
00000000000000000000000001111110
01111110-b
char c=a+b;
00000000000000000000000000000101
00000000000000000000000001111110
00000000000000000000000010000011
10000011-c
因为打印整形,先整型提升
11111111111111111111111110000011
10000000000000000000000001111101转换成原码
printf("%d",c);结果为-125
return 0;
}
11.2算术转换(大于等于整形)
如果某个操作符的各个操作致属于不同的类型,那么除非其中一个操作致的转换为另一个作数的类型,否则操作就无法进行。下面的展次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作致的类型在上而这个列表中排名较低,那么首先要转换为另外一个操作致的类型后执行运算
11.3操作符的属性
复杂表达式的求值有三个影响的因素
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序.
两个相邻的操作符先执行哪个取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性
操作符优先级
写代码要有唯一计算路径
标签:第十一天,int,C语言,++,操作符,整型,CPU,表达式 From: https://blog.csdn.net/2301_79600945/article/details/140624830