操作符的分类:
操作符可以分为以下几类:
算术操作符
+ - * / %
1、除了%d操作符之外,其他几个操作符可以用于整数和浮点数。
2、对于/操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3、%操作符的两个操作数必须为整数。返回的是整出之后的余数。
移位操作符
<<左移操作符
移位规则:左边抛弃,右边补0
int num=10;
00000000 00000000 00000000 00001010 num在内存中的二进制
00000000 00000000 00000000 00010100 num左移一位产生的结果
num<<1 但实际上num在没有被赋值的情况下,自身的值不会变化
eg:
int main()
{
int a=1;
int b=a<<2;
printf("%d\n"a,b);
return 0;
}
结果为:a=1,b=2
用二进制序列表示为:
a: 00000000 00000000 00000000 00000001
b: 00000000 00000000 00000000 00000010
>>右移操作符
移位规则:
右移运算分两种:
int num=-1;
假设num是-1;
这样内存中存储-1的补码为32个全1
11111111 11111111 11111111 11111111
算数右移:左边用原该值的符号位填充
11111111 11111111 11111111 11111111
由于是负数所以符号位为1,即左边补1
逻辑右移:左边补0
011111111 11111111 11111111 11111111
1、逻辑移位: 左边用0填充,右边丢弃
int num=10;
00000000 00000000 00000000 00001010 num在内存中的二进制
00000000 00000000 00000000 00010100 num左移一位产生的结果
num<<1 但实际上num在没有被赋值的情况下,自身的值不会变化
eg:
int main()
{
int a=1;
int b=a<<2;
printf("%d\n"a,b);
return 0;
}
结果为:a=2,b=1
用二进制序列表示为:
a: 00000000 00000000 00000000 00000010
b: 00000000 00000000 00000000 00000001
2、算术移位:左边用原该值的符号位填充,右边丢弃
eg:
int main()
{
int a=-1;
int b=a>>1;
printf("%d\n"a,b);
return 0;
}
结果为:a=-1;b-1;
警告 :对于移位运算符,不要移动负数位,这是标准为定义的。
eg:
int sum=10;
num>>-1;//error
位操作符
&//按位与
| //按位或
^按位异或
注:他们的操作数必须是整数。
eg:
int main()
{
int a=-1;
int b=a>>1;
printf("%d\n"a,b);
return 0;
}
结果为:a=-1;b-1;
一道变态的面试题:不能创建临时变量(第三个变量),实现两个数的交换。
eg:
int main()
{
int a=-1;
int b=a>>1;
printf("%d\n"a,b);
return 0;
}
结果为:a=-1;b-1;
#include<stdio.h>
int main()
{
int a=10;
int b=20;
a=a^b;
b=a^b;
printf("a=%d b=%d\n",a,b);
return 0;
}
赋值操作符
赋值操作符是一个很棒的操作符,他可以让你得到一个之前你不满意的值。也就是可以给自己重新赋值。
i
nt weight=120;//体重
weight=89;//不满意就赋值
double salary=10000.0;
salary=200000.0;//使用赋值操作符赋值。
赋值操作符可以连续使用,比如:
int a=10;
int x=20;
int y=20;
a=x=y+1;//连续赋值
但是:
x=y+1;
a=x;
这样的写法更加清晰有条理,而且易于调试。
复合赋值符:+= -= *= /= %= >>= <<= &= |= ^=
这些运算符,都可以写成复合的效果。
eg:
int x=10;
x=x+10;
x+=10;//复合赋值
//这样写会使我们的代码更加简洁。
单操作符
&取地址:
int arr[10]={0}
printf("%d\n",sizeof(arr))://40 数组名单独放在sizeof内部,数组名表示整个数组
printf("%d\n",sizeof(arr+0))://4 arr+0:表示的是数组首元素的地址
数组名:表示数组首元素的地址 arr+1=+4
&数组名——数组名表示整个数组 &arr+1=+40
放在sizeof内部的表达式不参与运算(sizeof求表达式在编译期间,一般表达式在运行期间运算)
eg:
int a=1;
short s=3;
sizeof(s=a+5);
结果为:a=1;s=3;
“~按位取反(符号位也取反)”
前置++ 前置--
eg:
#include<stdio.h>
int main()
{
int a=10;
int x=++a;
//先对a进行自增,然后再使用a,也就是表达式的值是a自增之后的值。x 为11。
int y=--a;
//先对a进行自减,然后再使用a,也就是表达式的值是a自减之后的值。x=9。
return 0;
}
后置++ 后置--
eg:
#include<stdio.h>
int main()
{
int a=10;
int x=a++;
//先对a使用,然后再自加,x 为10,之后a变为11。
int y=a--;
//先对a使用,然后再自减,y=10,之后a变为9。
return 0;
}
“*”间接访问操作符
eg:
#include<stdio.h>
int main()
{
int a=10;
int x=a++;
//先对a使用,然后再自加,x 为10,之后a变为11。
int y=a--;
//先对a使用,然后再自减,y=10,之后a变为9。
return 0;
}
“(类型)”强制类型转换符
eg:
int a=10;
a=(int)3.14
eg:
#include<stdio.h>
int main()
{
int i=0;a=0;b=2;c=3;d=4;
i=a++&&++b&&d++;
//i=a++||++b||d++;
结果为:
当a=0时:
a=1,b=2,c=3,d=4;
//a=1,b=3,c=3,d=4;
当a=1时:
a=1,b=3,c=3,d=4;
//a=2,b=2,c=3,d=4;
条件操作符
exp1 ? exp2 exp3
int main() { int a=0; int b=0;
return 0;}intmax=a>b?a:b;
逗号表达式
int a=1; int b=2; int c=(a>b,a=b+10,ab=a+1);//逗号表达式 c=2
下标引用、函数调用和结构成员
1、[ ]
操作数:一个数组名+一个索引值
int arr[ 10];//创建数组
arr[9]=10;//实用下标引用操作符
[ ]的操作数是arr和9
int main()
{
int arr[10]={0};
arr[5]=5;=*(arr+5)=5;
2、()
函数调用操作符(函数名也是一个操作符,是函数所在地址)
3、访问一个结构的成员
结构体.成员名
->结构体指针-.成员名
#include<stdio.h>
struct stu
{
char name [20];
char id[13];
int age;
}