C语言第十二课(中):操作符详解【单目、关系、逻辑、条件操作符】

news2024/10/5 12:45:57

目录

前言:

一、单目操作符!、-、+、&、sizeof、~、--、++、*、(类型):

        1.逻辑反操作!:

        2.正负值操作符-、+:

        3.取地址操作符 &与解引用操作符 *:

        ①.取地址操作符&:

        ②.解引用操作符 *:

        4.类型长度计算sizeof:

        5.按位取反~:

        6.前置与后置++、--操作符:

        7.强制类型转换(类型):

二、关系操作符>、>=、<、<=、==、!=:

三、逻辑操作符&&、||:

四、条件操作符:

五、总结:


前言:

        前面我们对操作符进行了简单的分类:

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

        而在上一篇文章中我们学习了算数、移位、位与赋值操作符的相关知识。本文我将继续按照顺序,带领小伙伴们继续学习单目、关系、逻辑、条件这些我们在编写代码时常用的操作符。

一、单目操作符!、-、+、&、sizeof、~、--、++、*、(类型):

        单目操作符,通俗的来讲就是只有一个操作数的操作符。是一类在进行操作时,只对一个操作数进行处理的操作符。

        1.逻辑反操作!:

        单目操作符' ! '表示逻辑反操作,即在逻辑层面表示“”、“”、“”等含义,例如:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int flag = 1;
	if (flag)
	{
		printf("FLAG\n");
	}
	if (!flag)
	{
		printf("!flag\n");
	}
	return 0;
}

        编译运行查看输出打印结果:

        我们可以看到,在我们定义了一个值为1的变量flag后,我们使用了if分支语句进行了判断,判断的条件即为变量flag,此时flag的值为1判断为逻辑“真”执行打印操作将“ FLAG ”字样打印在了我们的屏幕上。

        接着我们又使用另一个if分支语句进行了判断,此时的判断条件变成了对flag进行逻辑反操作,也就是此时flag为1,判断为“真”,逻辑取反,为“假”,则不执行第二个if语句中的操作,不打印字样“ !flag ”。

        这样我们就知道了逻辑反操作符的作用方式了,那么它的作用会对值产生影响吗?我们一起来验证一下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int flag1 = 5;
	int flag2 = !flag1;
	int flag3 = !flag2;
	printf("flag1 = %d\n", flag1);
	printf("flag2 = %d\n", flag2);
	printf("flag3 = %d\n", flag3);
	return 0;
}

        我们首先定义了一个值为5的变量flag1,接着定义了一个值为对flag1逻辑取反操作的变量flag2,又定义了一个值为对flag2逻辑取反操作的变量flag3。即flag2、flag3为两个对flag1连续进行两次逻辑取反操作的变量,并将它们的值全部打印在屏幕上,我们把它编译运行看看结果:

        我们可以看到,该操作符在执行时是会对操作数的值造成影响的,当值为5时为真(在计算机的逻辑判断中,0为假,非0为真),进行逻辑取反后值变为0为假再次进行逻辑取反操作后不会变为原本的值,而是变为了逻辑“真”值1

        2.正负值操作符-、+:

        很多小伙伴们看到这里可能会有疑问了,上面不是说单目操作符指的是只有一个操作数的操作符吗?可是在执行加减操作时的操作符操作的是两个操作数呀?在这里小伙伴们应当注意,这里我们要学习的符号' - '和' + ',不是指算数运算中的加法和减法运算,而是用于表示数值政府的正负值操作符:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int flag1 = 5;
	int flag2 = -flag1;
	int flag3 = +flag1;
	int flag4 = +flag2;
	printf("flag2 = %d\n", flag2);
	printf("flag3 = %d\n", flag3);
	printf("flag4 = %d\n", flag4);
	return 0;
}

        我们可以看到,通过使用这两个单目操作符,我们可以改变数据元素值的正负,同时我们也看到,在正数前面使用正号' + '时,数据元素的之不会发生变化 ,故正数前的' + '可以省略,同时,由于正号不会对数据元素的值造成影响,所以绝大多数情况下会被省略,在我们编写代码的过程中,除了用于标记值的正负供我们自己进行区分外,基本不会用到:

        3.取地址操作符 &与解引用操作符 *:

        ①.取地址操作符&:

        在我们的代码编写过程中,取地址操作符的使用可以说是随处可见了,在我们之前学习传址调用时,取地址操作符' & '也是很关键的一个操作符。而该符号的作用也很简单,它的作用就是读取出操作数在我们电脑内存中的存储地址。它的操作对象有很多种,其中就包括了常量变量数组等等:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	int arr[] = { 1,2,3,4,5 };
	printf("变量 a 的存储地址为:%p\n", &a);
	printf("数组arr的存储地址为:%p\n", arr);
	return 0;
}

        我们通过编译器的内存查看窗口来验证我们取出的地址是否正确。

        首先我们来看我们的程序编译运行结果,打印出了变量与数组的存储地址:

        接着我们先来验证打印出的地址是否为内存中变量a的存储地址

        我们可以看到内存中变量a的存储地址的确为000000249EAFFB54

        然后我们来验证打印出的地址是否为内存中数组arr的存储地址

        可以看到内存中数组arr的存储地址也确实为000000249EAFFB78

        ②.解引用操作符 *:

        取地址操作符' & '也常常与解引用操作符' * '结合起来进行使用,使用它可以将我们使用取地址操作符取出的地址存储起来

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	printf("变量 a 在内存中的存储地址为:%p\n", &a);

	int* p = &a;
	//通过使用解引用操作符,可以将使用取地址操作符&取出的数据存储地址存储起来
	//我们定义的变量a为int类型,故用于存储其地址的p的类型应当对应为int*类型
	printf("变量 a 在内存中的存储地址为:%p\n", p);

	return 0;
}

        编译运行后,我们看到在屏幕打印出的地址中,通过结合使用取地址操作符和解引用操作符能够成功存储我们取出的地址:

        并且在取得地址后,也可以通过使用解引用操作符,对该地址内的数据进行操作

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	int* p = &a;
	*p = 20;
	printf("变量 a 的值为:%d\n", a);
	return 0;
}

        其实,取地址操作符,就像是通过一个工具(&),拿到了某人(某数据)家的门牌号(存储地址),并用另一个工具(*)把这个门牌号(存储地址)记录下来,并能够通过这个工具(*)记录的门牌号(存储地址)找到这个人(该数据)的家,并对这个人(该数据)家中的人(数据)进行操作:

        4.类型长度计算sizeof:

        各位小伙伴们在这里要注意了,sizeof 既是一个关键字,同时也是一个操作符,其功能是用于计算操作数的类型长度(以字节为单位)的。:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	printf("变量 a 的长度为:%d\n", sizeof(a));
	printf("类型int的长度为:%d\n", sizeof(int));
	return 0;
}

        通过编译运行结果我们可以看到,这里打印出的并不是变量a的值,而是变量a的数据类型,即int类型的类型长度(以字节为单位)

        并且作为一个操作符,在使用时sizeof 后的括号在一定情况下可以省略,即sizeof后是变量名时可以省略,而当它后面是类型名时,括号不能省略,会直接报错:

        接着,我们要注意操作符sizeof内部的表达式不参与计算

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	short b = 20;
	printf("%d", sizeof(b = a + 10));
	printf("变量 b 的值为:%d\n", b);
	return 0;
}

        我们看到,sizeof操作符后括号内的计算并没有执行,仍为原值:

        并且我们通过观察也发现,虽然变量a与变量b的数据类型不同,但操作符sizeof所计算的仍然是括号内更靠前的变量b的数据类型长度。原因是其中的变量a为整形,在存储时将会在内存中开辟四个字节的空间,而变量b为short类型,在内存中仅占两个字节,若想要将四个字节的数据放进两个字节的空间中,将会发生截断只放入两个字节的数据还有两个字节的数据将不会被放入

        5.按位取反~:

        按位取反操作符~很好理解,我们前面学习过,数据在内存中存储时,存储的是其所对应的二进制补码,而~操作符,就是将操作数的二进制补码的每一位都进行取反操作,这里的每一位也包括符号位在内,没有例外:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 0;
	int b = ~a;
	printf("变量 a 的值为:%d\n", a);
	printf("变量 b 的值为:%d\n", b);
	return 0;
}

        我们都知道变量a,即0的二进制补码为:

0的二进制补码:0000 0000 0000 0000 0000 0000 0000 0000

        对其进行按位取反操作,即b的二进制补码则为:

b的二进制补码:1111 1111 1111 1111 1111 1111 1111 1111

        而二进制补码全为1的数值为-1,即b的值为-1。编译运行验证结果,我们可以得出,按位取反操作包括符号位在内,在每一位上均进行取反操作

        6.前置与后置++、--操作符:

        ++和--操作符很常用也很简单,++表示将值+1,--表示将值-1

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	printf("初始变量 a 的值为:%d\n", a);
	a++;
	printf("++后变量 a 的值为:%d\n", a);
	a--;
	printf("--后变量 a 的值为:%d\n", a);
	return 0;
}

        我们在这里初始化变量a的值为1,然后对其进行++,使得变量a的值进行了加一操作变为2,接着又对其进行--变量a的值便又进行了减一操作变为1:

        而关于++和--操作,我们需要注意的是忙着两个操作符在前置与后置时所起到的作用是不同的

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	printf("变量   a 的值为: % d\n", a);
	printf("\n");
	int b = a++;
	printf("后置++ b 的值为: % d\n", b);
	printf("变量   a 的值为: % d\n", a);
	printf("\n");
	
	a = 1;
	//重置变量a
	int c = ++a;
	printf("前置++ c 的值为: % d\n", c);
	printf("变量   a 的值为: % d\n", a);
	printf("\n");
	
	a = 1;
	//重置变量a
	int d = a--;
	printf("后置-- d 的值为: % d\n", d);
	printf("变量   a 的值为: % d\n", a);
	printf("\n");
	
	a = 1;
	//重置变量a
	int e = --a;
	printf("前置-- e 的值为: % d\n", e);
	printf("变量   a 的值为: % d\n", a);

	return 0;
}

        通过观察,我们可以得出结论:前置时先操作再赋值,后置时先赋值再操作

        即当后置++时,先将a的值1赋值给b,再将变量a进行了加一操作后变为2,此时变量b的值为1而变量a的值为2;当前置++时,先将变量a进行加一操作变为2,再将2赋给变量b,此时变量a与变量b的值均为2

        同理,当后置--时,先将a的值1赋值给b,再将变量a进行了加一操作后变为0,此时变量b的值为1而变量a的值为0;当前置--时,先将变量a进行减一操作变为0,再将0赋给变量b,此时变量a与变量b的值均为0

        7.强制类型转换(类型)

        在我们编写代码时,在一个工程项目中往往会用到很多种不同的数据类型,而不同的数据类型在进行赋值等操作时,就有可能会出现错误:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	float b = 3.14;
	a = b;
    printf("变量 a 的值为:%d\n", a);
	return 0;
}

        我们可以看到,变量a的数据类型为整型变量int,而变量b的数据类型为浮点型float,在进行赋值时因为数据类型不同,导致了赋值操作的失败:

        所以在这种情况下想要进行处理时,就应当对数据类型进行强制转换

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	float b = 3.14;
	a = (int)b;
	printf("变量 a 的值为:%d\n", a);
	return 0;
}

        在这种情况下强行进行赋值时应当将float类型的变量b强制转换为int类型后再进行赋值。而我们在编写代码时应当注意尽可能避免强制类型转换的使用,因为进行强制类型转换时虽然可以去除系统警告,但是有可能会导致部分数据的丢失。故不到万不得已尽量不要去使用

二、关系操作符>、>=、<、<=、==、!=:

        关系操作符的使用很简单,基本没有什么可讲的,但我们在使用时仍需要注意一些小的陷阱,例如要注意不要将赋值操作符' = '与关系操作符' == '搞混

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	int b = 2;
	int c = 2;
	int d = 1;
	int e = 1;
	int f = 1;
	if (b > a)
	{
		if (c >= b)
		{
			if (d < c)
			{
				if (e <= d)
				{
					if (f == e)
					//注意区分赋值操作符=与关系操作符==
					{
						printf("NICE!!!\n");
					}
				}
			}
		}
	}

	return 0;
}

三、逻辑操作符&&、||:

        逻辑操作与操作符' && '与逻辑操作或操作符' || '同样使用简单,均表示逻辑层面的“与”和“或”。逻辑与操作符' && '表示其两边的表达式均为真时为真,否则为假; 逻辑或操作符' || '表示当其两边的表达式有任一表达式为真时为真,均为假时为假。在使用时同样需要注意区分按位与操作符' & '与逻辑与操作符' && '按位或操作符' | '与逻辑或操作符' || '

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	int b = 0;
	if (a || b)
	{
		if (a && b)
		{
			printf("HEHE\n");
		}
		else
		{
			printf("LALA\n");
		}
	}
	return 0;
}

四、条件操作符:

        条件操作符也叫做三目操作符,原因是其操作数最多可以有三个

exp1 ? exp2 : exp3

        他表示,对表达式exp1进行判断,若判断为真则执行表达式exp2,若判断为假则执行表达式exp3。例如:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 5;
	int b = 0;
	if (a > 5)
	{
		b = 3;
	}
	else
	{
		b = -3;
	}
	printf("变量 b 的值为:%d\n", b);
	return 0;
}

        上述代码的编译运行结果为:

        该代码可以通过使用条件操作符简化为:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 5;
	int b = 0;
	b = a > 5 ? 3 : -3;
	printf("变量 b 的值为:%d\n", b);
	return 0;
}

        编译运行可以得到同样的结果,并且采用这样的形式,我们的代码直接减少了七行,大幅提高了我们代码的空间效率,可以使我们的代码在完成目标功能的前提下使用更少的空间

五、总结:

        至此,我们今天关于单目、关系、逻辑和条件操作符的介绍就到此为止了,这些操作符应用极其广泛,是我们编写代码过程中的好帮手,希望各位下伙伴们下去以后多多思考和理解,勤加练习,熟练掌握相关的原理和用法,提高自己的代码编写工作效率。

         希望各位小伙伴们能从今天的介绍中获得一些收获和启发,我也十分荣幸能为各位小伙伴们的学习生活提供一些帮助。彗星般的人生可以短暂,但绝不黯淡或沉沦!

        新人初来乍到,辛苦各位小伙伴们动动小手,三连走一走 ~ ~ ~  最后,本文仍有许多不足之处,欢迎各位看官老爷随时私信批评指正!

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

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

相关文章

数据结构与算法基础(王卓)(3)

前置&#xff1a; //#include<iostream> #include<stdlib.h>//存放exit#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define MAXlength 100 //初始大小为100&…

小程序开发音视频问题汇总及解决方案

目录 问题一&#xff1a;开发音视频&#xff0c;必用的两个小程序组件live-player和live-pusher&#xff0c;他们做什么用的&#xff0c;怎么才能使用&#xff1f; 问题二&#xff1a;一个页面只能插入一个 问题三&#xff1a;真机调试图片预览及视频全屏无反应 问题四&am…

图库 | 图存储的基础概念

前言 图存储的全称叫图数据库存储引擎或图数据库存储层&#xff08;组件&#xff09;。在功能层面&#xff0c;它负责图数据库或图数仓的数据的持久化存储。因为存储距离用户层的应用较图计算更为遥远&#xff0c;过往很少有论著会专门讲述图存储环节&#xff0c;但笔者要说的…

Python搭建虚拟环境

一、简介 1.特点&#xff1a; python的虚拟环境类似于虚拟机&#xff0c;能够创建一个独立的python运行环境&#xff0c; 虚拟环境中的安装的第三方依赖包和全局环境中的包相互独立。 2.环境 1. python3.3以上版本(自带venv模块&#xff0c;若已安装则可直接改变环境变量来…

【软件安装】Linux中RabbitMQ的安装

① 本篇是基于Linux操作系统中的安装&#xff0c;故先准备一个干净的Linux操作系统。本文中所有的操作基于CentOS8进行安装演示&#xff1b; ② 接下来的演示文本中&#xff0c;红色字体为操作步骤&#xff0c;黑色字体为解释说明&#xff1b; ③ 确保Linux系统中已经安装好必…

LightGBM 实现基于内容的个性化推荐

大家好&#xff0c;本文中&#xff0c;我将和大家一起学习如何训练 LightGBM 模型来估计电子商务广告的点击率的推荐系统的例子。将在Criteo数据集上训练一个基于LightGBM的模型。 LightGBM是一个基于树的梯度提升学习算法框架。是基于分布式框架设计的&#xff0c;因而非常高…

汇川伺服电机位置控制模式参数配置

1. 基本控制参数设置 1&#xff09;设置位置控制模式 2&#xff09;绝对值位置线性模式 2.端子输入参数设置 1&#xff09;将输入端子使能失效 3. 位置控制参数设置 1&#xff09;将位置来源设置为2&#xff1a;多段位位置指令 4.通信参数设置 1&#xff09;波特率设置为960…

单元测试我们需要知道哪些?

前言趁着刚读完《认知天性》这书&#xff0c;书有一点这样说&#xff1a;「我们学习行为更多凭着直觉&#xff0c;即使我们已经看到了科学数据&#xff0c;但我们也不愿意去相信自己的直觉存在问题。」那和我们单元测试有什么关系呢&#xff1f;这时我突然有一个问题&#xff1…

19-28-hive-数据类型-DDL

19-hive-数据类型-DDL&#xff1a; 基本数据类型 Hive 数据类型Java 数据类型长度例子TINYINTbyte1byte 有符号整数20SMALINTshort2byte 有符号整数20INTint4byte 有符号整数20BIGINTlong8byte 有符号整数20BOOLEANboolean布尔类型&#xff0c;true 或者falseTRUE FALSEFLOAT…

【Python】Labelme/PIL读取图片朝向错误解决

文章目录一、问题背景二、产生原因三、解决方案一、问题背景 发现使用labelme直接读取含imageData&#xff08;将图片bytes数据使用base64编码后的str数据&#xff09;的json文件时&#xff0c;读上来的图片会发生自动旋转的问题。比如原先是横放的图&#xff0c;读进来后就成…

虚拟化基本知识及virtio-net初探

QEMU/KVM是在Linux中被广泛使用的虚拟化技术之一&#xff0c;而virtio作为一个半虚拟化I/O事实上的标准[1]&#xff0c;是QEMU/KVM在I/O虚拟化部分的默认实现。virtio-net是virtio标准中的网卡设备&#xff0c;被广泛应用。本文将会沿着虚拟化&#xff0c;virtio半虚拟化I/O&am…

非对称风险模型

推荐模型&#xff1a;非对称性风险&#xff0c;让自己置身于一个好结果比坏结果影响大得多的环境中 比如投资&#xff0c;将85%~90%投入到极低风险的资产中&#xff08;国债&#xff09;&#xff0c;来享受确定性收益&#xff1b;剩下的投入的10%~15%投入到极高风险资产中&…

使用FeatureTask多线程优化in,提高查询速度

场景是这样的&#xff1a;使用in查询数据的时候&#xff0c;in的数量越多&#xff0c;效率越低&#xff0c;所以一个优化的思路是&#xff0c;缩小in查询的数量&#xff0c;用多线程的方式查询缩小数量后in的sql&#xff0c;并行查询。 直接上代码&#xff1a; public List&l…

Linux零基础入门(四)Linux实用操作

Linux零基础入门&#xff08;四&#xff09;Linux实用操作前言Linux实用操作一 各类小技巧&#xff08;快捷键&#xff09;1 ctrl c 强制停止2 ctrl d 退出或登出3 历史命令搜索4 光标移动快捷键5 清屏二 软件安装1 Linux系统的应用商店2 yum命令3 apt命令 - 扩展三 systemct…

全光谱台灯对孩子有伤害吗?儿童用台灯的好处和坏处是什么

全光谱台灯是指灯光色谱丰富度与太阳光一般全面的台灯&#xff0c;这样的灯光照射下的任何物体&#xff0c;不但颜色丰富多彩&#xff0c;而且极其真实&#xff0c;无限接近太阳光下的真实色彩&#xff0c;对人眼舒适度有巨大的提升&#xff0c;所以全光谱台灯不但对孩子无害&a…

5G无线技术基础自学系列 | MU-MIMO原理

素材来源&#xff1a;《5G无线网络规划与优化》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 MU-MIMO是指多个用户在上下行数据传输时…

算法实操:Python代码实现直插排序(含有序在前有序在后)

【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… 自学并不是什么神秘的东西&#xff0c;一个人一辈子自学的时间总是比在学校学习的时间长&a…

[附源码]SSM计算机毕业设计音乐网站JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

用结构体解决实际问题中构造数据类型

用结构体解决实际问题中构造数据类型。 实验内容 &#xff08;1&#xff09;题目&#xff1a;编写input()和output()函数输入&#xff0c;输出5个学生的数据记录。学生数据定义如下&#xff1a; #define N 5struct student{ char num[6];char name[8];int score[4];} stu[N];…

anaconda安装paddle(安装CUDA,CUDNN)

前言 为什么会写这样一篇呢&#xff0c;应该早晚会用到paddlelite&#xff0c;所以paddle还是要学的&#xff0c;与其在飞桨平台上跑&#xff0c;不如在自己电脑上跑。我以为安装paddle只需要三行代码&#xff1a; # 打开Anaconda Prompt conda create -n paddle python3.9 c…