C语言入门篇(八)

news2024/11/15 4:22:03

前言
  本篇分享的是部分操作符的概念与用法,从经典例题入手,带你快速了解和掌握。
  收录专栏:浅谈C语言

操作符详解上

  • 1. 操作符分类
  • 2. 算术操作符
  • 3. 移位操作符
    • 3.1 左移操作符
    • 3.2 右移操作符
  • 4. 位操作符
  • 5. 赋值操作符
  • 6. 单目操作符
    • 6.1 单目操作符介绍
    • 6.2 sizeof 和 数组
  • 7. 关系操作符
  • 8. 逻辑操作符
  • 9. 条件操作符

1. 操作符分类

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

2. 算术操作符

包括 + - * / %

例如:计算 3/2

#include<stdio.h>
int main()
{
	int a=3/2;
	printf("%d\n",a)
	return 0;
}

如果你觉得这样写,就大错特错了。

🍤 运行结果:

在这里插入图片描述
这是因为这里的 a 是整型的,计算出的结果就是整型,会自动舍去小数点后的数字。

更改 a 的类型为浮点数:

int main()
{
	double a = 3 / 2;
	printf("%lf\n", a);
	return 0;
}

其实,这样也是不对的。

🍤 运行结果:

在这里插入图片描述

仔细观察就会发现,这里的 a 虽然是 double 类型的,但 3 和 2 都是整形的, 3/2 计算后是 1,然后再将 1 装换成 double 型的赋给 a。

所以当计算的结果会出现浮点数时,除号的两端只要有一个小数就可以。

int main()
{
	//下面三种方式都可以计算出 1.5
	double a = 3.0 / 2.0;
	//double a = 3.0/2;
	//double a = 3 / 2.0;
	printf("%lf\n", a);
	return 0;
}

注:
🍥 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数

🍥 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法

🍥 除法中,除数不可以为 0

🍥 % 操作符的两个操作数必须为整数。返回的是整除之后的余数

3. 移位操作符

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

移位操作符的操作数只能是整数。
移动的是二进制,因为能够处理的是二进制的信息

3.1 左移操作符

移位规则:左边抛弃、右边补0

例如:

#include<stdio.h>
int main()
{
	int a = 15;
	printf("%d\n",a<<1);//移动就是a中的2进制信息
	return 0;
}

🍤 图解:

在这里插入图片描述

🍤 运行结果:

在这里插入图片描述

3.2 右移操作符

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

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

在C语言没有明确规定倒是算术右移还是逻辑右移,一般编译器上采用的是算术右移。

例如:

int a = -1;	

在这里插入图片描述

对于移位运算符,不要移动负数位,这个是标准未定义的。

例如:

int a = 15;
a>>-1;//error

移位移动的是补码的二进制序列

//tip:
int a = 15;
	//00000000000000000000000000001111 - 原码
	//00000000000000000000000000001111 - 反码
	//00000000000000000000000000001111 - 补码

	int b = -15;
	//10000000000000000000000000001111 - 原码
	//11111111111111111111111111110000 - 反码(原码的符号位不变,其他位按位取反得到的就是反码)
	//11111111111111111111111111110001 - 补码(反码+1就是补码)
	
	//整数在内存中存储的是补码
	//计算的时候也是使用补码计算的

4. 位操作符

位操作符有:(也是操作二进制位)

& //按位与
| //按位或
^ //按位异或

🍩上述的操作数必须是整数。

例如:

// & 操作符
#include<stdio.h>


int main()
{
	int a = 3;
	//00000000000000000000000000000011 - 补码
	int b = -5;
	//10000000000000000000000000000101
	//11111111111111111111111111111010
	//11111111111111111111111111111011 - 补码

	int c = a & b;
	//& -- 对应二进制位有0则为0,两个同时为1,才是1
	//00000000000000000000000000000011
	//11111111111111111111111111111011
	//00000000000000000000000000000011 - 补码
	
	printf("%d\n", c);//3
	return 0;
}
// | 操作符
#include<stdio.h>
int main()
{
	int a = 3;
	//00000000000000000000000000000011 - 补码
	int b = -5;
	//10000000000000000000000000000101
	//11111111111111111111111111111010
	//11111111111111111111111111111011 - 补码
	
	int c = a | b;
	// | - 按(2进制)位或 - 对应的二进制位有1则为1,两个同时为0才是0
	//00000000000000000000000000000011
	//11111111111111111111111111111011
	//11111111111111111111111111111011 - 补码
	//11111111111111111111111111111010
	//10000000000000000000000000000101 - -5
	printf("%d\n", c);//-5
	return 0;
}
// ^ 操作符
#include<stdio.h>
int main()
{
	int a = 3;
	//00000000000000000000000000000011 - 补码
	int b = -5;
	//10000000000000000000000000000101
	//11111111111111111111111111111010
	//11111111111111111111111111111011 - 补码
	//
	int c = a ^ b;
	//^ - 按二进制位异或 -对应的二进制位相同为0,相异为1
	//00000000000000000000000000000011
	//11111111111111111111111111111011
	//11111111111111111111111111111000 - 补码
	//11111111111111111111111111110111
	//10000000000000000000000000001000 - -8
	
	printf("%d\n", c);//-8
	return 0;
}

实例1:交换2个整型变量

要想交换两个变量的值,最常见的方法是再创建一个变量,帮助我们实现:

#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	//交换
	int tmp = a;//临时变量 tmp
	a = b;
	b = tmp;
	printf("交换前:a=%d b=%d\n", a, b);
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

如果不创建临时变量(第三个变量),可以实现两个整数的交换吗?
回答是可以的

方法一:


#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	a = a + b;
	b = a - b;
	a = a - b;
	printf("交换前:a=%d b=%d\n", a, b);
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

方法二:使用 ^ 操作符实现

#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	printf("交换前:a=%d b=%d\n", a, b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

🍤 运行结果:

在这里插入图片描述
异或操作符也支持交换律
例如:

//a^a -> 0
//a^0 = a
#include<stdio.h>
 int main()
{
	int a = 3;
	int b = 5;
	int c= a^b^a;
	int d= a^a^b;
	printf("%d %d\n", c, d);
	return 0;
}

🍤 图解:
a ^b ^a=b
在这里插入图片描述

同样地,a^a^b=a

🍤 运行结果:

在这里插入图片描述

实例2:求一个整数存储在内存中的二进制中1的个数。

//方法1
#include <stdio.h>
int main()
{
	int num = 10;
	int count = 0;//计数
	while (num)
	{
		if (num % 2 == 1)
			count++;
		num = num / 2;
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}
//方法2:
#include<stdio.h>
int main()
{
	int num = -1;
	int i = 0;
	int count = 0;//计数
	for (i = 0; i < 32; i++)
	{
		if (num & (1 << i))
			count++;
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}
//方法3,优化版本
#include <stdio.h>
int main()
{
	int num = -1;
	int i = 0;
	int count = 0;//计数
	while (num)
	{
		count++;
		num = num & (num - 1);
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}

5. 赋值操作符

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。

int weight = 120;//体重
weight = 89;//不满意就赋值
double salary = 10000.0;
salary = 20000.0;//使用赋值操作符赋值

赋值操作符可以连续使用
例如:

int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值

这样的代码感觉怎么样?
那同样的语义,你看看:

x = y+1;
a = x;

可见,下面的写法更加清晰爽朗而且易于调试。

复合赋值符

+= 
-=
*=
/=
%=
>>=
<<=
&=
|=
^=

这些运算符都可以写成复合的效果。
例如:

int x = 10;
x = x+10;
x += 10;//复合赋值,与上面等式等价
//但下面复合语句明显更加简洁。

其他运算符也是一样的道理。

6. 单目操作符

6.1 单目操作符介绍

!           逻辑反操作
-           负值
+           正值
&           取地址
sizeof      操作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问操作符(解引用操作符)
(类型)       强制类型转换

🍩单目操作符只有一个操作数

实例1:

// ! 操作符
//非 0 为真
#include<stdio.h>
int main()
{
	int flag = 5;
	if (flag == 0)
	{
		printf("hehe\n");
	}
	if (!flag)//这里当 flag 为假时,才会打印hehe
	{
		printf("hehe\n");
	}
	if (flag)
	{
		printf("haha\n");
	}
	return 0;
}

🍤 运行结果:

在这里插入图片描述

实例2: -

// - 操作符
#include<stdio.h>
int main()
{
	int a = 5;
	int b = -a;
	printf("%d\n", b);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

实例3: &

// & * 操作符
#include<stdio.h>
int main()
{
	int a = 10;
	//pa是指针变量
	int* pa = &a;//&-取地址操作符-取出a的地址

	*pa = 20;//解引用操作符(间接访问操作符)-单目操作符-通用pa中存放的地址,找到指向的空间(内容)
	//同时也更改了a 的内容
	int c = *pa;
	printf("a=%d c=%d\n",a, c);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

实例4:在计算数据类型所占内存大小时,可以使用 sizeof 操作数

🍥 sizeof不是函数,是操作符
🍥 sizeof计算的是类型创建变量的大小,单位是字节

//sizeof 操作符:
#include <stdio.h>
int main()
{
 int a = 10;
 printf("%d\n", sizeof(a));
 printf("%d\n", sizeof(int));
 printf("%d\n", sizeof a);
 //printf("%d\n", sizeof int);//不允许这样计算,说明 sizeof 不是函数
 return 0;
}

实例5: ~

// ~ 按补码二进制位取反
#include<stdio.h>
int main()
{
	int a = 0;
	printf("%d\n", ~a);
	//00000000000000000000000000000000
	//11111111111111111111111111111111 - 补码
	//11111111111111111111111111111110
	//10000000000000000000000000000001 -1
	return 0;
}

🍤 运行结果:

在这里插入图片描述

实例6:前置 ++ 、 后置 ++

//前置++:先对变量进行自增,然后使用该变量
int main()
{
	int a = 1;
	int b = ++a;//前置++,先++,后使用
	//a=a+1,b=a
	printf("a=%d b=%d\n", a, b);//2 2
	return 0;
}

🍤 运行结果:

在这里插入图片描述

//后置++:先对a先使用,再自增
#include<stdio.h>
int main()
{
	int a = 1;
	int b = a++;//后置++,先使用,后++
	//b=a,a=a+1
	printf("a=%d b=%d\n", a, b);//2 1
	return 0;
}

🍤 运行结果:

在这里插入图片描述
前置--、后置--等同

6.2 sizeof 和 数组

实例:

#include <stdio.h>
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{
	printf("%d\n", sizeof(ch));//(4)
}
int main()
{
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));//(1)
	printf("%d\n", sizeof(ch));//(3)
	test1(arr);
	test2(ch);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

7. 关系操作符

>
>=
<
<=
!=   用于测试“不相等”
==      用于测试“相等”

🍩编写过程中 == 和 = 不要写错

实例:判断闰年

#include<stdio.h>
int main()
{
	int y = 0;
	scanf("%d", &y);
	//1. 能被4整除,并且不能被100整除
	//2. 能被400整除是闰年
	if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
	{
		printf("闰年\n");
	}
	else
	{
		printf("不是闰年\n");
	}
	return 0;
}

8. 逻辑操作符

&&     逻辑与--并且
||     逻辑或--或者
1&2----->0
1&&2---->1
// & 两边二进制补码计算,相同为1,不同为0
// && 两边同为真,结果也是真,用 1 表示;只要有一个为假,结果就是假,用 0 表示
1|2----->3
1||2---->1
// | 两边二进制补码进行计算,只要有一个 1 就是 1;当两边都为 0 时,才是0
// || 两边只有一个真时,就为真;都是假时,才为假

实例1:

// &&
#include <stdio.h>
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
	printf("a = %d b = %d c = %d d = %d\n", a, b, c, d);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

实例2:

// ||
#include <stdio.h>
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++||++b||d++;
	printf("a = %d b = %d c = %d d = %d\n", a, b, c, d);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

9. 条件操作符

exp1 ? exp2 : exp3

实例:

//如果 a>5,则 b=3
//如果 a<=5,则 b=-3
if (a > 5)
        b = 3;
else
        b = -3;

上述代码可以转换成条件表达式:

#include <stdio.h>
int main()
{
	int a ;
	scanf("%d", &a);
	int b = a > 5 ? 3 : -3;
	printf("%d\n", b);
	return 0;
}

🍤 运行结果:

在这里插入图片描述

使用条件表达式实现找两个数中较大值

#include <stdio.h>
int main()
{
	int a, b ;
	scanf("%d %d", &a, &b);
	int c = a > b ? a : b;
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/798846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytest常用的命令行

查看Pytest所有的命令行 Pytest -h 结果&#xff1a; 我们使用pytest时&#xff0c;忘记了会有哪些命令行&#xff0c;或是忘记哪个命令行怎么用&#xff0c;可以进行查看下。 执行参数 命令行参数 (1)--collect-only&#xff0c;打印出具体的执行从目录到用例执行的具体显…

is与==的区别

是比较运算符&#xff0c;用于比较两个值是否相等&#xff0c;结果返回布尔类型True或False is操作符是比较值所在的内存地址是否相同&#xff0c;结果返回布尔类型True或False aList [a,b,c] bList [a,b,c] # True print(aList bList) # False print(aList is bList)# 12…

【计算机网络】应用层协议 -- 安全的HTTPS协议

文章目录 1. 认识HTTPS2. 使用HTTPS加密的必要性3. 常见的加密方式3.1 对称加密3.2 非对称加密3.3 非对称加密对称加密 4. 引入CA证书4.1 CA认证4.2 数据签名4.3 非对称机密对称加密证书认证4.4 常见问题 5. 总结 1. 认识HTTPS HTTPS全称为 Hyper Text Tranfer Protocol over …

Java---第八章(字符串-----String,StringBuilder 和 StringBuffer)

Java---第八章 字符串String字符串的常用方法StringBuilder和StringBuffer常用方法 对比String 和StringBuilder 和 StringBuffer 字符串 String 特性&#xff1a; String 类位于java.lang包中&#xff0c;无需引入&#xff0c;可直接使用String 类是由final修饰的&#xff…

【cpolar内网穿透工具】

文章目录 cpolar内网穿透工具.md概述什么是cpolar&#xff1f;cpolar可以用在哪些场景&#xff1f; 1. 注册cpolar帐号1.1 访问官网站点&#xff1a;[https://www.cpolar.com](https://link.zhihu.com/?targethttps%3A//www.cpolar.com/) 1.2 注册帐号 2. 下载Windows版本cpol…

SpringBoot使用Redis对用户IP进行接口限流

使用接口限流的主要目的在于提高系统的稳定性&#xff0c;防止接口被恶意打击&#xff08;短时间内大量请求&#xff09;。 一、创建限流注解 引入redis依赖 <!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId&g…

RK3399平台开发系列讲解(内核调试篇)Valgrind 内存调试与性能分析

🚀返回专栏总目录 文章目录 一、为什么要学会Valgrind二、什么是内存泄露三、Valgrind的移植四、Valgrind相关参数沉淀、分享、成长,让自己和他人都能有所收获!😄 📢Valgrind 是一个开源的内存调试和性能分析工具,用于帮助开发者找出程序中的内存错误,如内存泄漏、使…

Ansys 光学解决方案在 A/VMR 中的应用 | 以Apple Vision Pro 为例(1)

说明 苹果公司于近期在 WWDC23 上发布了其第一代空间计算设备 Apple Vision Pro。作为一款跨世代的融合现实产品&#xff0c;Apple Vision Pro 融合了业界尖端的光学技术以实现最佳的用户体验。在这个系列的文章中&#xff0c;我们将以 Apple Vision Pro 中的各项光学应用为引子…

获奖!CFS十二届财经峰会,群硕持续耕耘数字化科技沃土

7月26-27日&#xff0c;CFS2023第十二届财经峰会暨2023可持续商业大会&#xff0c;于北京成功举办。在这场中国经济影响力思想盛会上&#xff0c;群硕获评2023数字化转型推动力奖。 ## 开拓创新&#xff0c;屡获殊荣 CFS财经峰会设立于2012年&#xff0c;是国内众多财经及大众…

【 Python 全栈开发 - 人工智能篇 - 45 】决策树与随机森林

文章目录 一、概念与原理1.1 决策树1.1.1 概念1.1.2 原理特征选择分割方法 1.1.3 优点与缺点1.1.4 Python常用决策树算法 1.2 随机森林1.2.1 概念1.2.2 原理1.2.3 优点与缺点1.2.4 Python常用随机森林算法 1.3 决策树与随机森林的比较1.3.1 相同之处1.3.2 不同之处 二、决策树算…

苍穹外卖Day01项目日志

1.软件开发流程和人员分工是怎样的&#xff1f; 软件开发流程 一个软件是怎么被开发出来的&#xff1f; 需求分析 先得知道软件定位人群、用户群体、有什么功能、要实现什么效果等。 需要得到需求规格说明书、产品原型。 需求规格说明书 其中前后端工程师要关注的就是产品原…

C# 继承,封装,多态等知识点

一&#xff1a;面向对象的三大特征&#xff1a;继承性&#xff0c;封装性&#xff0c;多态性 1&#xff1a;继承性&#xff1a;继承主要描述是类与类之间的关系&#xff0c;通过继承可以在无需重新编写原有的类的情况下&#xff0c;对原有的类的功能进行扩展。 2&#xff1a;封…

【Lua学习笔记】Lua进阶——协程

文章目录 协程协程的定义和调度StatusRunning 协程 协程是一种并发操作&#xff0c;相比于线程&#xff0c;线程在执行时往往是并行的&#xff0c;并且线程在创建销毁执行时极其消耗资源&#xff0c;并且过长的执行时间会造成主进程阻塞。而协程可以以并发时轮值时间片来执行&…

法大大携手盘子女人坊,以数字化唤醒国风摄影新体验

第三方数据显示&#xff0c;目前&#xff0c;我国共有163万家摄影相关企业&#xff0c;有约1900个从事摄影相关业务的品牌&#xff0c;且预计到2025年艺术摄影市场规模将达到7063.18亿元。艺术摄影行业作为在时代进步、科技发展以及人民生活水平提高的推动下逐渐发展起来的行业…

flutter:角标

角标应该非常常见了&#xff0c;以小说app为例&#xff0c;通常会在小说封面的右上角上显示当前未读的章数。 badges 简介 Flutter的badges库是一个用于创建徽章组件的开源库。它提供了简单易用的API&#xff0c;使开发者可以轻松地在Flutter应用程序中添加徽章效果。 官方文…

day42-Live User Filter(实时用户过滤器)

50 天学习 50 个项目 - HTMLCSS and JavaScript day42-Live User Filter&#xff08;实时用户过滤器&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport…

【深度学习】【三维重建】windows11环境配置tiny-cuda-nn详细教程

【深度学习】【三维重建】windows11环境配置tiny-cuda-nn详细教程 文章目录 【深度学习】【三维重建】windows11环境配置tiny-cuda-nn详细教程前言确定版本对应关系源码编译安装tiny-cuda-nn总结 前言 本人windows11下使用【Instant Neural Surface Reconstruction】算法时需要…

饱和(非饱和)激活函数

1.什么是饱和&#xff08;非饱和&#xff09;激活函数 若h(x)满足&#xff1a;&#xff0c;则h(x)称为饱和激活函数&#xff0c;例如sigmoid和tanh&#xff0c;否则为非饱和激活函数&#xff0c;例如Relu及其变体。 2.非饱和激活函数的优势有两点 能解决所谓的“梯度消失”问…

剑指offer10-II.青蛙跳台阶问题

这道题和上一道斐波那契一模一样&#xff0c;如果你要到达第n个台阶&#xff0c;你有两种方法&#xff0c;第一种是到达n-1级然后跳一下&#xff0c;第二种是到大n-2级然后跳两下&#xff0c;所以到达n级的方法数就是到达n-1级的方法数加上到达n-2级的方法数。其实就是和斐波那…

Hightopo 使用心得(5)- 动画的实现

在前一篇文章《Hightopo 使用心得&#xff08;4&#xff09;- 3D 场景 Graph3dView 与 Obj 模型》中&#xff0c;我们通过使用 ht.Default.startAnim() 让一个直升飞机飞了起来。其实&#xff0c;在 HT for Web 中&#xff0c;有多种手段可以用来实现动画。 我们这里仍然用直升…