这里写目录标题
- 1.位操作符
- 1.1左移操作符(<<)
- 1.2右移操作符(>>)
- 1.3按位与操作符(&)
- 1.4按位或操作符(|)
- 1.5异或操作符(^)
- 1.6取反操作符(~)
- 练习
- 2.逗号表达式
- 3.下标访问[]、函数调用()
- 3.1下标引用操作符 [ ]
- 3.2函数调用操作符 ()
- 4.操作数的优先级
1.位操作符
1.1左移操作符(<<)
二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
将操作数的所有位向左移动指定的位数。左移 n 位相当于乘以 2 的 n 次方。
//左移操作符(<<)
int main() {
int a = 5;//0000 0101 = 5
int b = a << 1;//0000 1010 = 10
printf("a << 1 = %d", b);
return 0;
}
输出结果:
a << 1 = 10
1.2右移操作符(>>)
二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补 0,负数左补 1,右边丢弃。
将操作数的所有位向右移动指定的位数。右移n位相当于除以 2 的 n 次方。
//右移操作符(<<)
int main() {
int a = 14;//0000 1110 = 14
int b = a >> 1;//0000 0111 = 7
printf("a >> 1 = %d", b);
return 0;
}
输出结果:
a >> 1 = 7
注意:上述左移和右移操作符是位移运算符,不要移动负数位数,这是标准未定义的。
1.3按位与操作符(&)
对两个操作数二进制的每一位执行逻辑与操作,如果两个相应的位都为 1,则结果为 1,否则为 0。
//按位与(&)
int main() {
int a = 5;//0000 0101 = 5
int b = 3;//0000 0011 = 3
//0000 0001 = 1
int result = a & b;
printf("a & b = %d", result);
return 0;
}
输出结果:
a & b = 1
1.4按位或操作符(|)
对两个操作数二进制的每一位执行逻辑或操作,如果两个相应的位都为 0,则结果为 0,否则为 1。
//按位或(|)
int main() {
int a = 5;//0000 0101 = 5
int b = 3;//0000 0011 = 3
//0000 0111 = 7
int result = a | b;
printf("a | b = %d", result);
return 0;
}
输出结果:
a | b = 7
1.5异或操作符(^)
对两个操作数二进制的每一位执行逻辑异或操作,如果两个相应的位值相同,则结果为 0,否则为 1。
//按位异或(^)
int main() {
int a = 5;//0000 0101 = 5
int b = 3;//0000 0011 = 3
//0000 0110 = 6
int result = a ^ b;
printf("a ^ b = %d", result);
return 0;
}
输出结果:
a ^ b = 6
注:&、|、^三种位操作符的操作数必须是整数。
1.6取反操作符(~)
对操作数的每一位执行逻辑取反操作,即将每一位的 0 变为 1,1 变为 0。
取反的具体过程:
1.先将操作数化为补码
2.再对补码进行取反(0 变为 1,1 变为 0)
2.将取反后的补码再转变为原码,得出的值就是原操作数取反后的值。
//取反(~)
int main() {
int a = 5;
//a原码:0000 0101 = 5
//a补码:0000 0101
int result = ~a;
//a取反:1111 1010
//然后再将取反后的补码转换为原码
//反码:1111 1001
//原码:1000 0110 = -6
printf("~a = %d", result);
return 0;
}
输出结果:
~a = -6
注:&、|、^三种位操作符的操作数必须是整数。
练习
1.在不创建临时变量(第三个变量)的情况下,实现两个数的交换
int main() {
int a = 5;
int b = 3;
printf("交换前 a=%d b=%d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("交换后 a=%d b=%d", a, b);
return 0;
}
用个人的话来发现其中的规律,就是两个整数(假设A和B)异或后得到的数(假设为C)
用C去异或A或B其中一个数,所得的数为没有参加异或的那个数。
例如
∵A ^ B = C
∴C ^ A =B或者C ^ B =A
借助这一特性不需要创建临时变量也可以实现两个数的交换。
2.逗号表达式
逗号表达式就是用逗号隔开的多个表达式。
逗号表达式,从左至右一次执行。整个表达式的结果是最后一个表达式的结果。
//代码一
int main() {
int a = 1,b = 2;
int c = (a = b -a, a = b + 10, a, b = a + 1);//所以c应该是最后一项b = a + 1的值
printf("%d", c);
return 0;
}
输出结果:
13
//代码二
int main() {
int a = 1, b = 2, c = 3;
if (a = b + 1, c = a / 2, c > 0) {
printf("c=%d", c);
}
return 0;
}
/*
(a = 3,c=1,1>0) 1>0成立等于1,所以执行if语句
*/
输出结果
c=1
3.下标访问[]、函数调用()
3.1下标引用操作符 [ ]
//数组下标[
int main() {
int arr[5] = { 1, 2, 3, 4, 5 };
// 0 1 2 3 4
printf("%d", arr[4]);//5
return 0;
}
arr[4]
下标操作符[]的操作数是:数组名arr 和 4(下标索引位)
3.2函数调用操作符 ()
//函数的定义
int add(int x,int y) {
int z = x + y;
return z;
}
//函数调用()
int main() {
printf("%d", add(1, 2));//3
return 0;
}
add(1,2)
函数操作符()的操作数是:函数名add,1,2
问题一:
()函数调用操作符最少有几个操作符?
1个,也就是只写个函数名,即无参函数。
问题二:
sizeof()是不是函数呢?
sizeof不是函数,记住不是函数!sizeof是操作符!!!
上代码!
//sizeof是操作符
int main(){
int a = 10;
//int n = sizeof(a);
int n = sizeof a;
printf("%d\n", n);
return 0;
}
结果发现sizeof(a)的效果和sizeof a相同,所以证明sizeof不需要函数调用操作符()也能正常运行,而调用函数必须要有()才可以调用。
4.操作数的优先级
优先级和结合性决定了表达式求值的计算顺序
如果优先级相同,这时看结合性。大部分运算符都是(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符(=)。