C语言操作符详解(深入理解)

导读:本篇文章讲解 C语言操作符详解(深入理解),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1.位操作符

 

注意:对于位操作符,他们的操作数必须是整数

1.按位“异或”运算(^)

按位“异或”运算符是双目运算符,其功能是将参与运算的两数的对应二进制位相“异或”。

运算规则:位置相同结果为0,相异为1。

运算特点:a:0异或任何数 == 任何数  b: 1异或任何数 == 任何数取反 c: 任何数异或自己 == 把自己置0

支持交换律:10 ^ 20 ^ 10 == 10 ^ 10 ^ 20 == 0 ^ 20 == 20

应用举例:

(1):实现两个值的交换,而不必 使用临时变量。这种方法因为不会产生进位,所以不会溢出,建议采用!!!


void Swap(int*xp, int*yp){
	*xp ^= *yp;
	*yp ^= *xp;
	*xp ^= *yp;
}

(2):快速判断两个值是否相等

            return   ((a ^ b)  == 0)

2.按位或(|)

运算规则:每一位上,有1为1,同0 为0.

注:自己和自己按位或,得其本身。

3.按位与(&)

运算规则:每一位上,同为1时为1,否则为0.

注:任意一个数和-1按位与,得其本身。

按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清0,保留低八位,可作 a & 255运算(255的二进制数为00000000…0011111111)。

编写代码实现:求一个整数存储在内存中的二进制中的1的个数。

方法一:(缺陷:不能计算负数!)

#include<stdio.h>
#pragma warning(disable:4996)
int main(){
	int num = 10;
	int count = 0;//计数
	while (num){
		if (num % 2 == 1){//括号里的条件用于检测最低比特位
			count++;
		}
		num = num / 2;
	}
	printf("二进制中1的个数 = %d\n", count);
	system("pause");
	return 0;
}

方法二:(缺陷:因为结果为 32,这里必须循环32次

#include<stdio.h>
#pragma warning(disable:4996)

int main(){
	int num = -1;
	int i = 0;
	int count = 0;//计数
	for (i = 0; i < 32; i++){
		if (((num >> i) & 1) == 1){
			count++;
		}
	}
	printf("二进制中1的个数 = %d\n", count);
	system("pause");
	return 0;
}

方法三:(一次消去一个二进制位中的1,效率高)

#include<stdio.h>
#pragma warning(disable:4996)
int main(){
	int num = -1;
	int count = 0;//奇数
	while (num){
		count++;
		num = num&(num - 1);
	}
	printf("二进制中1的个数 = %d\n", count);
	system("pause");
	return 0;
}

2.移位操作符

1.左移操作符

移位规则:最高位丢弃,最低位补0.(左移操作符本身与数据正负性无关。)

2.右移操作符

移位规则:1.逻辑移位(对应无符号数)左边用0补充,右边丢弃 2.算数移位(对应有符号数)左边用原该值的符号位填充(正数补0,负数补1),右边丢弃

正数:15 >>>> 2

首先转化为二进制,15的二进制为0000 1111;将二进制数向右移两位,高位补0,得到 0000 0011;最后将二进制数转化为十进制数,0000 0011转化为3

所以,15 >>>>2 = 3

负数:因为负数的符号位(最高位)为1,而无符号右移要在最高位补0,所以32位二进制要写全。带符号右移(>>),高位补的是符号位,前24位都是1

eg:-15>>>>2

首先转化为二进制,-15的二进制为1111 1111 1111 1111 1111 1111 1111 0001;将二进制数向右移两位,高位补0,得到0011 1111 1111 1111 1111 1111 1111 1100

最后将二进制数转化为十进制数,0011 1111 1111 1111 1111 1111 1111 1100转化为十进制数为1,073,741,820

3.逻辑操作符

1.逻辑与(&&)

即为and,当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false.(C语言中,0为假,非0为真)

比如:12 && 23 的结果就是1,12&& -1 的结果是1,123&& 0 的结果是0

&&还具有短路的功能,即如果第一个表达式为假,则不计算第二个表达式,例如,if(0 && printf(“hello”));后面的表达式不会执行!!

2.逻辑或(||)

逻辑或,当两个条件中有任一个条件满足,“逻辑或”的运算结果就为真

eg:12 || 1 = 1,12 || 0 = 1,0 || 0 = 0

当第一个表达式为真,则不计算第二个表达式!!!

360经典面试题

#include<stdio.h>
#pragma warning(disable:4996)
int main(){
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;//a = 0,不会进行第一个逻辑与后的操作
	//i = a++ || ++b || d++;第二个逻辑或后的操作不会进行
	printf("a = %d\n b = %d\n c = %d\n d = %d\n i = %d\n", a, b, c, d, i);//1 2 3 4 0
	//printf("a = %d\n b = %d\n c = %d\n d = %d\n i = %d\n", a, b, c, d, i);//1 3 3 4 1
	system("pause");
	return 0;
}

C语言操作符详解(深入理解)

4.三元运算符

运算规则:exp1 ? exp2 : exp3   第一个是表达式,剩余两个是值,条件表达式为真时,取第一个值,为假时,取第二个值。

注意点:如果两个定义了数据类型的变量,那么返回的结果就是范围大(精度高)的类型。

5.逗号表达式

(exp1,exp2,exp3,….expN)

注意点:1.从左向右依次执行;2.整个表达式的结果是最后一个表达式的结果。3.逗号表达式的优先级在所有运算符中最低 。

6.复杂表达式计算的问题

a*b + c*d + e*f

注释1:代码在计算的时候,由于 * 比 + 的优先级高,但是优先级并不能决定第三个 * 比第一个 + 执行早。

所以表达式的计算机顺序就可能是:

a * b
c * d
a*b + c*d
e * f
a*b + c*d + e*f
//或者:
a * b
c * d
e * f
a*b + c*d
a*b + c*d + e*f
#include <stdio.h>
int main()
{
    int i = 1;
    int ret = (++i)+(++i)+(++i);
    printf("ret = %d\n", ret);
	return 0;
}

注释:这段代码中的第一个 + 在执行的时候,第三个 ++ 是否执行,这个是不确定的,因为依靠操作符的优先级和结合性是无法决定第一个 + 和第三个前置 ++ 的先后顺序。

总结:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/110988.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!