1.对于右移操作符来说,有两种右移方式:
(1)算术右移:右边丢弃,左边补原符号位;
(2)逻辑右移:右边丢弃,左边补0;
2.
(1)&(按位与)操作符:
这里的按位是按二进制位,如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 3; //00000000000000000000000000000011
int b = 5; //00000000000000000000000000000101
int c = a & b; //00000000000000000000000000000001
printf("%d\n", c);
return 0;
}
输出结果为1;这里的规则是,两个数都为真,c才为真;
(2)|(按位或):
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 3; //00000000000000000000000000000011
int b = 5; //00000000000000000000000000000101
int c = a | b; //00000000000000000000000000000111
printf("%d\n", c);
return 0;
}
只要两个数的二进制位上其中有一个为真,c就为真;
(3)^(按位异或):
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 3; //00000000000000000000000000000011
int b = 5; //00000000000000000000000000000101
int c = a ^ b; //00000000000000000000000000000110
printf("%d\n", c);
return 0;
}
两个数的相应二进制位如果相同,则为假,不相同为真;
奇技淫巧:a^a = 0 a^0 = a
3.赋值操作符可以连续使用:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10;
int x = 0;
int y = 20;
a = x = y+1; //连续赋值
return 0;
}
4.逻辑反操作符:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0;
if(!a)
{
printf("haha");
}
return 0;
}
结果是会打印haha;
5.sizeof操作符(注意不是函数):用于计算对象所占空间的大小,单位是字节;
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10;
int arr[10] = {0};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof a);
printf("%d\n", sizeof(int [10]));
return 0;
}
sizeof后可以不加(),int [10]代表的是数组类型,相当于sizeof(int),定义变量时去掉变量名就是变量类型的代表方式。
例如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
short s = 5;
int a = 10;
printf("%d\n", sizeof(s = a + 2));
printf("%d\n", s);
return 0;
}
注意:sizeof里面的表达式不进行计算,所以s的值还是5,这涉及到内部程序编译顺序的问题:
首先,我们写的程序.c文件是源程序,它经过编译时,执行了sizeof指令,然后表达式就消失了,之后再进行链接,成为可执行程序.exe文件,这时进行执行的时候才进行表达式的计算。
6.逻辑与(&&)和逻辑或(||):
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("%d %d %d %d", a, b, c, d);
return 0;
}
输出结果为1,2,3,4;原因是逻辑与语句遇到第一个为假,则直接返回假值,不进行后面一系列运算,所以b、d的值不变;
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("%d %d %d %d", a, b, c, d);
return 0;
}
结果为1,3,3,4;原因是逻辑或语句遇到真值时会立刻返回真值,不进行后续运算。
7.下标引用操作符:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = {0};
printf("%d\n", arr[5]); //此为下标引用操作符,他的操作数有两个,一个为5,一个为arr;
return 0;
}
8.函数调用操作符:
()有多个操作数,一个是函数名,其他的是传递给函数的参数。
9.隐式类型转换:
c的整型算术运算总是至少以缺省整型类型的精度来进行的;
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升;
(1) 整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度;
因此,即使两个char类型的相加,在CPU执行时实际上也是要先转换为CPU内整型操作符的标准长度;
通用CPU是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换成int或unsigned int,然后才能送入CPU去执行运算。
整型提升是按照变量的数据类型的符号位来提升的。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char a = 3; //00000011 -> 00000000000000000000000000000011
char b = 127;//01111111 -> 00000000000000000000000001111111
char c = a + b; //00000000000000000000000010000010 然后截断成10000010存到c中;
printf("%d\n", c); //输出时再进行整形提升:11111111111111111111111110000010
return 0; //转换为原码10000000000000000000000001111101 结果为-126
}
发生整型提升的条件:
(1)算术运算:+ - * / %
(2)比较运算:> < >= <= == !=
(3)位运算:& | ^ << >>
例如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c = 1;
printf("%d\n", sizeof(c));
printf("%d\n", sizeof(+c));
printf("%d\n", sizeof(-c));
return 0;
}
结果为1 4 4;
(2)算术转换
一般是精度低的向精度高的转换,或者内存小的向内存大的转换。
10.复杂表达式求值影响因素:
其实这个影响因素在不同的编译器上运算法则很不同,没有固定的标准,所以作为优秀的程序员,往往需要把复杂拆成简单,多步拆成分布,避免错误重意代码产生。