1.算数操作符 (+,-,*,/,%)
1)%的两个操作数都必须是整数;返回的是余数。
2)/的两个操作数都为整数时,它的结果才为整数;只要有浮点类型的数结果就一定是浮点类型。
2.移位操作符(左移,右移)对整型而言
1)左移操作符:将数据的二进制序列向左移动左边的数丢弃,右边补0.
(在计数机中数据是以二进制补码的形式存储;正数的原码、反码、补码 相同;负数的补码形式是在原码的条件下除符号位其他全部取反,再加1;)
int a =10; b=a<<1; 可以得到b=20,a还是10。可以看出左移操作具有乘以2的效果。a的值本身不变,b是移后的值。
2)右移操作符:
@1:算术右移。将二进制序列进行右移时,将右边的数字丢弃,在左边补符号位。(大多数都是采用这种方法)
@2:逻辑右移。将二进制序列进行右移时,将右边的数字丢弃,在左边直接补零。(这种如果是移动一个负数,移完之后就会变成正数,错误太大)
测试编辑器采用算术右移,还是逻辑右移:
int a=-1;//11111111 11111111 11111111 11111111(补码)
a=a>>1;
printf("%d\n",a);
结果如果是-1,则是算术右移。
结果如果是正数,则是逻辑右移。
3.位操作(& ,|,^)
1)&:与。全1即为1.(任何一个数只要和1与操作,得到的结果就是该数的最低位二进制数0/1 0或者1)
2)|:或。有1即为1.全0即为0.
3)^:异或。不同为1,相同为0.(a^a==0 a^0==a)
例子:
比如: 15 0000 1111 4 个 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 0;
int ret = 0;
scanf("%d", &a);
ret = count_one_bits(a);
printf("%d\n", ret);
system("pause");
return 0;
}
int count_one_bits(int x)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if ((x >> i) & 1 == 1)
{
count++;
}
}
return count;
}
4.单目操作符
int flag=10; int flag=0;
printf("%d\n",!flag);//0 printf("%d\n",!flag);//1
2)&:取地址操作符。
@1:对于变量和数组而言
#include<stdio.h>
int main()
{
int a = 10;
int arr[10] = { 0 };
printtf("%p\n", &a);//取的是变量a的地址
printtf("%p\n", arr);//取的是数组首地址
printtf("%p\n", arr+1);//指向下一个元素的地址
printtf("%p\n", &arr);//指向数组首地址地址
printtf("%p\n", &arr+1);//指向的是数组的末尾地址
}
arr数组名相当于取的是首地址;&arr相当于取的是数组的地址。
@2:取函数的地址
#include<stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", &test);
}
&test取的是函数地址。
5)sizeof:计算变量大小;数组大小。
#include<stdio.h>
int main()
{
int a = 10;
int arr[10] = { 0 };
printf("%d\n", sizeof (a));//4
printf("%d\n", sizeof (int));//4
printf("%d\n", sizeof (arr));//40
printf("%d\n", sizeof (int [10]));//40
}
sizeof内部写的表达式根本就不参与运算:
#include<stdio.h>
int main()
{
short s = 0;
int a = 10;
printf("%d\n", sizeof(s = a + 8));//2
printf("%d\n", s);//0
printf("%d\n", a);//10
getchar();
}
源文件要变成可执行文件需要通过编译和执行两个过程,sizeof操作符是在编译是就可以得知数的类型的字节数,在编译阶段还没有创建a,s的变量,所以s得值还是原来的值,并没有将10+8的值赋给s。
6)~:对一个数的二进制按位取反。
#include<stdio.h>
int main()
{
int a = 10;
printf("%d\n", ~10);
//00000000 00000000 00000000 00001010 10
//11111111 11111111 11111111 11110101 ~10 是某个数的补码
//11111111 11111111 11111111 11110100 减1
//10000000 00000000 00000000 00001011 符号位不变其他取反,即-11
getchar();
}
7)前置++,后置++。
@1变量的增值:
#include<stdio.h>
int main()
{
/*int a = 10;
int b = 0;
printf("%d\n", b = ++a);//11 先++,再运算
printf("%d\n", a);//11
getchar();
*/
int a = 10;
int b = 0;
int a = 10;
int b = 0;
printf("%d\n", b = a++);//10 先运算再++
printf("%d\n", a); } //11
@2:指针的增值
#include<stdio.h>
int main()
{
int a[10] = { 0 };
int *p = a;
printf("%p\n", p);//数组首地址
//printf("%p\n", p++);//和上面一样,但执行完成后p指向下一个元素的地址,即在之前的基础上加了4个字节
printf("%p\n", ++p);//在数组首地址的基础上先增加4个字节再打印出来
getchar();
}
8)*:解引用操作符。
#include<stdio.h>
int main()
{
int a = 10;
int *p = &a;//指针p
*p = 20;//*解引用p
printf("%d\n", a);
getchar();
}
解引用操作符可以决定访问多大的空间:
#include<stdio.h>
int main()
{
int a = 0x11223344;//16进制 一个数即为二进制的4位 这个数共有4个字节
int* p = &a;
*p = 0;//4个字节同时被赋值为0,因为指针类型是int型
//char * p = &a;
//*p = 0;//只能改变1个字节,因为指针类型是char型
getchar();
}
9)逻辑操作符:&&逻辑与
a+b&&c+d&&e+f:如果a+b为假则后面的表达式就不用再算了。
||逻辑或
a+b||c+d||e+f:如果a+b为真后面表达式就不用再算了。
10)条件操作符:三目操作符
max=a>b?a:b //如果前面表达式正确则把“:”前面的a赋值给max。否则将“:”后面的b赋值给max.
11)逗号表达式。
逗号表达式 c=(a>b,a=b+10,a,b=a+1)
从左向右依次运算,整个表达式的结果只取决于最后一个表达式的结果。
int a=1;
int b=2;
int c=(a>b,a=b+10,a,b=a+1);//a=2+10, 12, b=12+1
结果将b赋值给c, c=13