服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言操作符超详细讲解上篇

C语言操作符超详细讲解上篇

2022-11-08 13:51初学C语言者 C/C++

C 语言提供了丰富的操作符,有:算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符等。因为篇幅过大将分两篇讲解,让我们通读本篇来详细了解吧

前言

操作符主要内容包括:各种操作符的介绍,用表达式求值。

1、操作符的分类

  • 算术操作符
  • 移位操作符
  • 位操作符
  • 赋值操作符
  • 单目操作符
  • 关系操作符
  • 逻辑操作符
  • 条件操作符
  • 逗号表达式
  • 下标引用、函数调用和结构成员

2、算术操作符

 +  -  *  /  %  (加法 减法 乘法 取余 取模)
int main()
{
	int a = 9 / 2;//4
	float b = 9 / 2;
	int c = 9.0 / 2;
	float d = 9.0 / 2;//4.5
	float e = (float)9.0 / 2;

	printf("%d\n", a);
	printf("%f\n", b);
	printf("%d\n", c);
	printf("%f\n", d);
	printf("%f\n", e);
	return 0;
}

运行结果见下图:

C语言操作符超详细讲解上篇

C语言操作符超详细讲解上篇

C语言操作符超详细讲解上篇

通过例子可发现,变量的类型使用错误的话,结果也是错误的

  • 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数
  • 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法
  • % 操作符的两个操作数必须为整数。返回的是整除之后的余数

 

3、移位操作符

移位操作符的操作数只能是整数

<< 左移操作符
>> 右移操作符

3.1 左移操作符

  • 移位规则:左边抛弃、右边补0
  • 整数是 int 型,占4个字节,有32位表示。其中最高位表示符号,0为正,1为负
  • 整数在内存中存储的是补码的二进制,正数的原码、反码、补码是相同的
  • 操作符对整数操作的流程:

(1)先将整数的原码转换成反码

(2)反码 +1转换成补码

(3)最后对整数的补码进行操作

(4)操作结束后,将操作后的补码 -1 转换成反码

(5)将反码转换成最终的原码

  • 函数printf打印的是整数的原码

3.1.1 正数左移1位

代码如下(示例):

int main()
{
	int a = 5;
	int b = a << 1;//操作的补码二进制位,a本身结果不变
	printf("%d\n", a);//打印5
	printf("%d\n", b);// -10
	return 0;
}

C语言操作符超详细讲解上篇

结果运行见下图,与分析的结果一致,左移1位的效果相当于乘以2,左移在51单片机、STM32中,操作寄存器会经常用到。

C语言操作符超详细讲解上篇

3.1.2 负数左移1位

int main()
{
	int a = -5;
	int b = a << 1;//<< >> 操作的二进制位
	printf("%d\n", a);//打印-5
	printf("%d\n", b);// -10
	return 0;
}

C语言操作符超详细讲解上篇

运行结果见下图,和分析的结果一致

C语言操作符超详细讲解上篇

3.2 右移操作符

右移移位规则运算分两种:

  • 逻辑移位:左边用0填充,右边丢弃
  • 算术移位:左边用原该值的符号位填充,右边丢弃

3.2.1 正数右移1位

int main()
{
	int a = 5;
	int b = a >> 1;//右移不一定是除2

	printf("%d\n", a);//打印-5
	printf("%d\n", b);// -3
	return 0;
}

下面分析右移的过程:正数的原码、反码、补码一样

00000000 00000000 00000000 00000101 //5的二进制补码
//算术右移:左边用原该值的符号位1填充,右边丢弃1
00000000 00000000 00000000 00000010 //右移后的补码
//右移后的补码就是右移后的原码 2

结果见下图:

C语言操作符超详细讲解上篇

3.2.2 负数右移1位

int main()
{
	int a = -5;
	int b = a >> 1;//右移不一定是除2

	printf("%d\n", a);//打印-5
	printf("%d\n", b);// -3
	return 0;
}

下面分析右移的过程:

10000000 00000000 00000000 00000101 //-5的二进制原码
11111111 11111111 11111111 11111010 //反码
11111111 11111111 11111111 11111011 //补码:反码+1
//算术右移:左边用原该值的符号位1填充,右边丢弃1
11111111 11111111 11111111 11111101 //右移后的补码
11111111 11111111 11111111 11111100 //反码:补码-1
10000000 00000000 00000000 00000011 //原码 -3

结果见下图:

C语言操作符超详细讲解上篇

3.3 移位操作符说明

注意事项:

  • 右移操作符采用逻辑移位还是算术移位,取决于电脑编译器,我的是算术移位,所以举例以算术移位分析的,逻辑移位分析流程一样
  • 对于移位运算符,不要移动负数位,这个是标准未定义的,例如:
int num = 10;
num>>-1;//10右移-1位,这是错误的表达

 

4、位操作符

位操作符有:

& //按位与 相同为1, 相异为0
| //按位或 有1为1, 全0为0
^ //按位异或 相同为0, 相异为1
//注:他们的操作数必须是整数

int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	int d = a | b;
	int e = a ^ b;//异或
	//对应的二进制位:相同位0,相异为1
	printf("%d\n", c);// 打印3
	printf("%d\n", d);// -5
	printfan("%d\n", e);// -8	
	return 0;
}

00000000 00000000 00000000 00000011 3的补码
11111111 11111111 11111111 11111011 -5的补码
//按位与: 相同为1, 相异为0
00000000 00000000 00000000 00000011 3的补码,原码表示3
//按位或: 有1为1, 全0为0
11111111 11111111 11111111 11111011 -5的补码,原码表示-5
//按位异或: 相同为0, 相异为1
11111111 11111111 11111111 11111000 补码
11111111 11111111 11111111 11110111 反码
10000000 00000000 00000000 00001000 原码 -8

输出结果见下图,与分析一致:

C语言操作符超详细讲解上篇

4.1 练习 1

不能创建临时变量(第三个变量),实现两个数的交换

int main()
{
	int a = 3;
	int b = 5;

	printf("a=%d b=%d\n", a, b);
	//第一种,常用的方法,创建中间变量
	int tmp = a;
	a = b;
	b = tmp;	
	//第二种,不创建变量
	a = a + b;
	b = a - b;
	a = a - b;
	//第三种,不创建变量,很难想到
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a=%d b=%d\n", a, b);
	return 0;
}

4.2 练习 2

求一个整数存储在内存中的二进制中1的个数

//举例: 5 &1, 然后右移1位, 再&1
//00000000 00000000 00000000 00000101
//00000000 00000000 00000000 00000001

int main()
{
	int num = 0;
	scanf("%d", &num);
	int i = 0;
	int cnt = 0;
	//位操作
	for ( i = 0; i < 32; i++)
	{//每次右移一位就 &1
		if (1==((num>>i)&1))
		{
			cnt++;//所有位与1,相同为1,相异为0
		}
	}
	printf("%d", cnt);
	return 0;
}

 

总结

本文对部分操作符进行了,介绍,也分析了操作符的具体实现过程,这里了解原理即可,具体运算交给计算机执行,没必要每个都自己画图分析,耗时,不细心可能还会出错,32位二进制建议大家划分成4个字节,8位一组,好看一些,这在STM32 单片机对寄存器操作时,经常这样划分,一目了然。

到此这篇关于C语言操作符超详细讲解上篇的文章就介绍到这了,更多相关C语言 操作符内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/taibudong1991/article/details/123855462

延伸 · 阅读

精彩推荐
  • C/C++C语言快速幂取模算法小结

    C语言快速幂取模算法小结

    这篇文章主要介绍了C语言快速幂取模算法,包括了算法的分析与改进,是很多程序设计竞赛中常见的算法,需要的朋友可以参考下...

    C语言程序设计11182021-01-31
  • C/C++C++ Sqlite3的使用方法

    C++ Sqlite3的使用方法

    这篇文章主要介绍了C++ Sqlite3的使用方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    SolidMango8712021-09-10
  • C/C++C++11用两个线程轮流打印整数的实现方法

    C++11用两个线程轮流打印整数的实现方法

    这篇文章主要介绍了C++11用两个线程轮流打印整数的实现方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需...

    Augusdi8102021-09-27
  • C/C++C语言从txt文件中逐行读入数据存到数组中的实现方法

    C语言从txt文件中逐行读入数据存到数组中的实现方法

    下面小编就为大家带来一篇C语言从txt文件中逐行读入数据存到数组中的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小...

    C语言教程网4602021-04-23
  • C/C++使用C语言如何输出逆序数

    使用C语言如何输出逆序数

    逆序数的就是把一个数倒过来,例如:1234那么它的逆序数就为4321,我们该如何是实现呢?下面这篇文章主要给大家介绍了关于使用C语言如何输出逆序数的相关...

    无情必定上岸8552022-08-15
  • C/C++C语言实现定时器控制LED灯闪烁

    C语言实现定时器控制LED灯闪烁

    这篇文章主要为大家详细介绍了C语言实现定时器控制LED灯闪烁,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    weixin_533919579492021-11-03
  • C/C++C语言字符函数中的isalnum()和iscntrl()你都知道吗

    C语言字符函数中的isalnum()和iscntrl()你都知道吗

    这篇文章主要为大家详细介绍了C语言字符函数中的isalnum()和iscntrl(),文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    嵌入式@hxydj5592022-09-26
  • C/C++简单对比C语言中的fputs()函数和fputc()函数

    简单对比C语言中的fputs()函数和fputc()函数

    这篇文章主要介绍了简单对比C语言中的fputs()函数和fputc()函数,注意其之间的区别,需要的朋友可以参考下...

    C语言教程网10502021-03-09