文章目录
一、操作符介绍
1、算术操作符
2、移位操作符 (只能作用于整数,不能作用于浮点数)
移位时移动的是补码
右移的两种移动方法:
(1)算术右移:(通常情况使用)(右移则其数值除2)
右边丢弃,左边补充原符号位
原来正数补0;
原来负数补1.
(2)逻辑右移:(数值乘2的效果)
右边丢弃,左边补0
左移:左边丢弃,右边补0
注意事项:
对于移位运算操作符,不要移动负数位,该标准未定义。
例如:
int main()
{
int num=10;
num>>-1; //error
return 0;
}
3、位操作符(只能作用于整数,不能作用于浮点数)
(1)&, 按位与 (二进制位)
(2)|, 按位或 (二进制位)
(3)^, 按位异或 (二进制位):
相同为0,不同为1(任何数和0异或为其本身)
//按位与
int main()
{
int a=10; //00000000000000000000000000001010
int b=20; //00000000000000000000000000010100
int c=a&b; //是32位二进制数字“与”,二进制数字同1则1,反之为0,“与”后结果为00000000000000000000000000000000
printf("c=%d\n",c); //输出值为0
return 0;
}
//按位或
int main()
{
int a=10; //00000000000000000000000000001010
int b=20; //00000000000000000000000000010100
int c=a|b; //是32位二进制数字“与”,二进制数字有1则1,全0为0,“或”后结果为00000000000000000000000000011110
printf("c=%d\n",c); //输出值为由二进制转换为十进制为30
return 0;
}
//按位异或
int main()
{
int a=10; //00000000000000000000000000001010
int b=20; //00000000000000000000000000010100
int c=a^b; //是32位二进制数字“与”,二进制数字不同为1,相同为0,“或”后结果为00000000000000000000000000011110
printf("c=%d\n",c); //输出值为由二进制转换为十进制为30
return 0;
}
4、赋值操作符(1h14‘)
前面可以先定义一个值,后面不满意再重新赋值(使用赋值操作符赋值)(一个“=”号)
(1)连续赋值(不建议使用)
(2)复合赋值符1h15’
a=a+2 等价于 a+=2
a=a>>1 等价于 a>>=1
a=a&1 等价于 a&=1
5、单目操作符
(1)! ,真变假,假变真
int main()
{
int a=0;
if(!a)
{
printf("hehe\n");
}
return 0;
}
(2)sizeof
举例1:
int main()
{
int a=0;
char b='r';
char* p=&c;
int arr[10]={0};
printf("%d\n",sizeof(a)); //整型4个字节 a的括号可以省略
printf("%d\n",sizeof(int)); //整型4个字节,括号不可省略
printf("%d\n",sizeof(c)); //char类型占用1字节
printf("%d\n",sizeof(char)); //char类型占用1字节
printf("%d\n",sizeof(p)); //32位系统,指针占用4字节
printf("%d\n",sizeof(char*)); //32位系统,指针占用4字节
printf("%d\n",sizeof(arr)); //整型数组,其中10个元素,每个元素4字节,共计40字节
printf("%d\n",sizeof(int [10])); //整型数组,其中10个元素,每个元素4字节,共计40字节,对于数组也可以用类型来计算
return 0;
}
举例2:(易错)关于sizeof(arr)和函数调用
(7.24日 始)
void test1(int arr[]) //数组传参时,传递数组的首元素地址,此时arr为指针
{
printf("%d\n",sizeof(arr)); // 指针大小只有4字节(32位)/8字节(64位)
}
void test2(char ch[]) //数组传参时,传递数组的首元素地址,所以此时的ch为指针
{
printf("%d\n",sizeof(ch)); // 指针大小只有4字节(32位)/8字节(64位)
}
int main()
{
int arr[10]={0};
char ch[10]={0};
printf("%d\n",sizeof(arr)); //输出为整个整型数组的所占空间大小,4*10=40
printf("%d\n",sizeof(ch)); //输出为整个字符数组所占空间大小,1*10=10
test1(arr);
test2(ch);
return 0;
}
(3)按位取反(~)
int main()
{
int a=0;
//按位(2进制)取反
//0的二进制 00000000000000000000000000000000(补码)
//取反 11111111111111111111111111111111(补码)
// 11111111111111111111111111111110(反码) (补码+1)
// 10000000000000000000000000000001(原码)(反码取反,符号位不变) 得值为-1
printf("%d\n",~a);//内存存储为补码,打印出的为原码
return 0;
}
(4)++和- -
前置:先++,后使用
后置
int main()
{
int a=10;
printf("%d\n",++a); //先+ ,再打印,得值为11
printf("%d\n",a++); //先打印,再+,与上方分别打印时,得值为10
//如果两项一起打印时,都得值为11,因为上方a打印后自增1,所以a值变为11
return 0;
}
(5)* 间接引用操作符(解引用操作符)
(6)(类型)强制转换类型
int main()
{
int a=(int)3.14;
//int a=int(3.14) error
return 0;
}
6、关系操作符
7、逻辑操作符
(1)逻辑与&&:全真为真,一假则假
特点:左边为假时,右边无论是什么都不进行计算
举例1:(普通的逻辑与和逻辑或)
int main()
{
int a=1;
int b=2;
int c=a&&b;
int d=a||b;
printf("%d\n",c); //“逻辑与”,全真为真,输出1
printf("%d\n",d); //“逻辑或”,一真则真,全假为假,输出1
}
举例2:(易错点:“逻辑与”有一次判断为假时,后边无论是什么都不进行计算)
int main()
{
int i=0,a=0,b=2,c=3,d=4;
i=a++ && ++b && d++; //a++,先用再自增,此时a=0.左边为假,右边不进行计算
printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d); //输出值为1234
return 0;
}
**(2)逻辑或||:**一真则真,全假则假
举例:(易错点:“逻辑或”有一次判断为真时,后边无论是什么都不进行计算)
int main()
{
int i=0,a=1,b=2,c=3,d=4;
i=a++ || ++b || d++; //a++,先用再自增,此时a=1.第一次判断为真,右边不进行计算
printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d); //输出值为2234
return 0;
}
8、条件操作符
exp1?exp2,exp3
含义:判断表达式1真假,1为真时,执行表达式2;1为假时,执行表达式3
int main()
{
int a=10;
int b=20;
int max=0;
if(a>b)
max=a;
else
max=b;
printf("max =%d\n",max);
return 0;
}
等价于下方代码
int main()
{
int a=10;
int b=20;
int max=0;
max=(a>b?a:b);
printf("max =%d\n",max);
return 0;
}
9、逗号表达式
整个表达式从左至右依次计算,但是表达式的结果为最后一个表达式的结果
插图1h15‘32’‘
3个代码
int main()
{
int a=1;
int b=2;
int c=(a>b,a=b+10,a,b=a+1); //a>b为假,不执行;a=2+10=12; b=12+1=13,然后将b的值赋值给c
printf("%d\n",c);
return 0;
}
10、下标引用、函数调用、结果成员操作符
(1)下标引用操作符
操作数:一个数组名+一个索引值
(2)函数调用操作符
一般调用自定义函数的时候“()”就是函数调用操作符
至少有一个操作数,即为函数操作名
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); // 此处的()为函数调用操作符,其操作数为 get_max,a,b 至少有一个操作数,即为函数操作名
printf("max =%d\n",max);
return 0;
}
(3)访问一个结构的成员
“.” 结构体.成员名
结构体变量.成员名
//创建结构体类型--struct stu
struct stu
{
//成员变量
char name[20];
int age;
char id[20];
};
int main()
{
int a=10;
//使用struuct stu类型创建了一个学生对象s1,并初始化
struct stu s1={"张三",20,"20180109"};
printf("%s\n",s1.name);
printf("%d\n",s1.age);
printf("%d\n",s1.id);
return 0;
}
“->” 结构体指针->成员名
struct stu
{
char name[20];
int age;
char id[20];
};
int main()
{
int a=10;
//使用struuct stu类型创建了一个学生对象,并初始化
struct stu s1={"张三",20,"20180109"};
struct stu* ps=&s1;
printf("%d\n",ps->age); //左边为结构体指针,右边是成员名
printf("%d\n",ps->id);
printf("%s\n",ps->name);
return 0;
}
二、表达式求值
隐式类型转换
整型提升
插图 1h55‘43’‘
参与计算的变量 没有达到整型大小,都会整型提升
算术转换
三、操作符的属性
1、操作符的优先级
优先级由上至下
2、操作符的结合性
一些问题表达式(无法确定计算的唯一路径):
例如:ab+cd+e*f
c±-c(–优先级高于+)
代码3
代码4(2h26‘)