C learning_12 操作符前篇(算术操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符)

news2024/11/23 12:03:06

目录

算术操作符

移位操作符

移位规则

位操作符

交换两个整形变量的写法

赋值操作符

单目操作符

sizeof和数组的纠缠

++和--运算符

多组输入的方案

关系操作符

逻辑操作符


算术操作符

-- 加法操作符(+):用于将两个值相加。

-- 减法操作符(-):用于将两个值相减。

-- 乘法操作符(*):用于将两个值相乘。

-- 除法操作符(/):用于将两个值相除得到商。

-- 取余操作符(%):用于将两个值相除得到余数。

除法:

        1.整数除法(除号两边都是整数)

        2.浮点数除法(除号两边至少有一个小数) 

        3.除数不能为零,除零报错(error C2124: 被零除或对零求模)

取余:m % n

        1.余数范围为【1,n-1】

        2.取余的操作数必须都是整数

        3. 不能对零取余,取余报错(error C2124: 被零除或对零求模)

移位操作符

-- 左移操作符(<<):将一个二进制数向左移动指定的位数,相当于该数乘以2的移动次幂

-- 右移操作符(>>):将一个二进制数向右移动指定的位数,相当于该数除以2的移动次幂

移位规则

左移

        左边抛弃、右边补0

右移

        1. 逻辑移位(逻辑移位是指将二进制数进行无符号移位)

                左边用0填充,右边丢弃

        2. 算术移位(算术移位是指将二进制数进行有符号移位)

                左边用原该值的符号位填充,右边丢弃

算术右移举例
#include<stdio.h>
int main()
{
	//整数在内存中存储的是补码
	
	signed int a = 15;
	
	//正数原、反、补码相同
	//原码:0000 0000 0000 0000 0000 0000 0000 1111
	//反码:0000 0000 0000 0000 0000 0000 0000 1111
	//补码:0000 0000 0000 0000 0000 0000 0000 1111

	signed int b = -15;
	//负数原、反、补不同
	//原码:1000 0000 0000 0000 0000 0000 0000 1111
	//反码:1111 1111 1111 1111 1111 1111 1111 0000
	//补码:1111 1111 1111 1111 1111 1111 1111 0001

	//a、b右移1位 - 移动的就是a、b的补码的二进制序列
	int c = a >> 1;
	//           [补]                                    [舍] 
	//移位后补码:0[0]000 0000 0000 0000 0000 0000 0000 111[1]
	//反码:      0 0 000 0000 0000 0000 0000 0000 0000 111
	//原码:      0 0 000 0000 0000 0000 0000 0000 0000 111 - 对应十进制 - 7


	int d = b >> 1;
	//           [补]                                    [舍] 
	//移位后补码:1[1]111 1111 1111 1111 1111 1111 1111 000[1]
	//反码:      1 1 111 1111 1111 1111 1111 1111 1110 111
	//原码:      1 0 000 0000 0000 0000 0000 0000 0001 000 - 对应十进制 - -8

	printf("%d\n", c);
	printf("%d\n", d);
	return 0;
}

注意:移位运算不会对原数据有任何的改变。

警告⚠ :

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

例如:

                int num = 10;

                num>>-1;//error

  

位操作符

-- 按位与操作符(&):将两个二进制数对应的位相与

-- 按位或操作符(|):将两个二进制数对应的位相或

-- 按位异或操作符(^):将两个二进制数对应的位异或

#include<stdio.h>
int main()
{
	int a = 3;
	//补码:0000 0000 0000 0000 0000 0000 0000 0011
	int b = -5;
	//原码:1000 0000 0000 0000 0000 0000 0000 0101
	//反码:1111 1111 1111 1111 1111 1111 1111 1010
	//补码:1111 1111 1111 1111 1111 1111 1111 1011
	
	//& - 对于的补码序列有0为0,全1为1
	printf("%d\n",a & b);
	//3 补码:0000 0000 0000 0000 0000 0000 0000 0011
	//-5补码:1111 1111 1111 1111 1111 1111 1111 1011
	//  &   :0000 0000 0000 0000 0000 0000 0000 0011 - 对应十进制 - 3
	
	//& - 对于的补码序列有1为1,全0为0
	printf("%d\n", a | b);
	//3 补码:0000 0000 0000 0000 0000 0000 0000 0011
	//-5补码:1111 1111 1111 1111 1111 1111 1111 1011
	//  |   :1111 1111 1111 1111 1111 1111 1111 1011 - 补码
	//       1000 0000 0000 0000 0000 0000 0000 0101 - 原码 - 对应十进制 - -5

	// ^ - 对于的补码序列不同为1,相同为0
	printf("%d\n", a ^ b);
	//3 补码:0000 0000 0000 0000 0000 0000 0000 0011
	//-5补码:1111 1111 1111 1111 1111 1111 1111 1011
	//  ^   :1111 1111 1111 1111 1111 1111 1111 1000 - 补码
	//       1000 0000 0000 0000 0000 0000 0000 1000 - 原码 - 对应十进制 - -8
	return 0;
}

交换两个整形变量的写法

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

        这段代码展示了如何使用一个临时变量来交换两个变量的值。具体来说,代码中定义了两个整型变量a和b,并初始化为1和2。然后使用printf函数将它们的原始值打印出来。 接下来,代码定义了一个整型变量temp,并将a的值赋给temp,相当于把a的值复制到了temp中。然后,将b的值赋给a,相当于把b的值覆盖了a中原来的值。最后,将temp的值赋给b,相当于把a中原来的值存储到了b中。这样,a和b的值就互换了。 最后,代码使用printf函数再次将a和b的值打印出来,以显示它们已经被交换了。

  

#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	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和b,并初始化为1和2。然后使用printf函数将它们的原始值打印出来。

接下来,代码通过一系列的加减运算来交换a和b的值。首先将a和b的值相加,并将结果存储到a中。然后将新的a值减去旧的b值,并将结果存储到b中。最后将新a值减去刚才计算得到的新b的值,并将结果存储到a中。利用加减法运算完成了交换操作。最后,代码使用printf函数再次将a和b的值打印出来,以显示它们已经被交换了。注意,这种方法虽然不需要使用额外的变量来存储临时值,但需要进行多次加减运算,可能会影响代码的运行效率,同时由于是加法操作,会造成数据进行溢出。

#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	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;
}

        这也是一段C语言代码,同样实现了两个变量的值交换功能,但是它使用了异或运算(^)来完成交换操作。 具体地,首先定义了两个整型变量a和b,且分别赋值为1和2。然后输出交换前a和b的值。 接着,使用异或运算(^)按位进行交换,具体地,a先和b进行异或运算,然后将结果赋值给a。这时a变成了3(0011),同时由于异或运算支持交换律,所以此时b异或上a(即原来的a)就相当于b异或上新的a(即原来的a异或上原来的b),得到的结果赋值给b。这时b变成了1。最后再利用异或运算(^)完成a和b的值交换。 最后输出交换后a和b的值,即完成了值交换的操作。

赋值操作符

赋值操作符可以连续使用,

比如:

        int a = 10;

        int x = 0;

        int y = 20;

        a = x = y+1;//连续赋值

等价于:      

         int a = 10;

        int x = 0;

        int y = 20;

        x = y+1;

        a = x;

这样的写法是不是更加清晰,更加容易辨识。

复合赋值符:+=  -=  *=  /=  %=  >>=  <<=  &=  |=  ^=

单目操作符

单目操作符是一种只需要一个操作数的操作符,通常用于对单个变量或值进行操作。

sizeof和数组的纠缠

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

        在主函数中,首先定义了一个大小为10的int类型和char类型的数组arr和ch,分别使用sizeof打印出数组大小。此时,打印结果应该是40和10,因为一个int类型的元素占用4个字节,而数组中共有10个元素,所以整个数组占用40个字节。而一个char类型的元素占用1个字节,而数组中共有10个元素,所以整个数组占用10个字节。 然后调用test1和test2函数,分别将arr和ch数组作为参数传递给函数。在函数调用中,实际上传递的是数组的指针,即数组的首元素的地址。因此,在函数内部使用sizeof操作符打印出的大小为指针的大小,即在32位系统中为4个字节,而在64位系统中为8个字节。

++和--运算符

//++和--运算符
#include <stdio.h>
int main()
{
    int a = 10;

    //前置++和--
    int x = ++a;
    //先对a进行自增,然后再使用a,也就是表达式的值是a自增之后的值。x为11
    int y = --a;
    //先对a进行自减,然后再使用a,也就是表达式的值是a自减之后的值。y为10
    
    //后置++和--
    int x = a++;
    //先对a先使用,再增加,这样x的值是10,之后a变成11
    int y = a--;
    //先对a先使用,再自减,这样y的值是11,之后a变成10
    return 0;
}

        前置自增运算符“++”表示在使用变量之前先将变量的值加1,而后置自增运算符“++”表示先使用变量的值,然后再将变量的值加1。前置自减和后置自减运算符“--”也能使用相同的逻辑。

        在程序中,定义了一个整型变量a并初始化为10。接下来,使用前置自增运算符和前置自减运算符分别对变量a进行一次自增和自减操作,并将结果分别赋值给变量x和y。由于是前置运算符,因此表达式的值在使用变量之前就已经发生改变了,所以变量x和y的值分别为11和10。 接下来,再次使用变量a进行自增和自减操作,但这次使用的是后置自增“++”和后置自减“--”运算符。由于是后置运算符,表达式的值是先使用变量,然后再执行自增或自减操作,因此变量x和y的值分别为10和11,最后变量a的值变成了10。

        总结:前置自增和自减运算符在使用变量之前就对变量进行了加减操作,而后置自增和自减运算符在表达式的值确定之后才对变量进行加减操作。

#include<stdio.h>
int main()
{
	int a = 5;
	//0000 0000 0000 0000 0000 0000 0000 0101
	//0000 0000 0000 0000 0000 0000 0001 0000
	a |= (1 << 4);
	printf("%d\n", a);
	//0000 0000 0000 0000 0000 0000 0001 0101
	//1111 1111 1111 1111 1111 1111 1110 1111
	//0000 0000 0000 0000 0000 0000 0000 0101
	a &= (~(1 << 4));
	printf("%d\n", a);
	return 0;
}

多组输入的方案

#include<stdio.h>
int main()
{
	int n = 0;
	while (scanf("%d", &n) == 1)
	{
		printf("%d\n", n);
	}
	return 0;
}


#include<stdio.h>
int main()
{
	int n = 0;
	while (scanf("%d", &n) != EOF)
	{
		printf("%d\n", n);
	}
	return 0;
}


#include<stdio.h>
int main()
{
	//#define EOF    (-1)
	/*
		-1的补码
		1111 1111 1111 1111 1111 1111 1111 1111
		~(-1)
		0000 0000 0000 0000 0000 0000 0000 0000
		while(0)为假就不执行了
	*/
	int n = 0;
	while (~scanf("%d", &n))
	{
		printf("%d\n", n);
	}
	return 0;
}

关系操作符

>  >=  <  <=  !=   

        注意:不可以比较字符串

逻辑操作符

&&     逻辑与

||        逻辑或

计算结果是真,用1表示;计算结果为假,用0表示。

小试牛刀

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

        1.由于a++是后置++,所以a是先使用后自增,所以a++表达式是0,由于是逻辑与(&),并且逻辑与(&)具有短路的特点,只要有假就是假,后的表达式++b和d++都不会执行。

        所以结果是:1 2 3 4

        2.由于a++是后置++,所以a是先使用后自增,所以a++表达式是0,由于是逻辑或(|),需要执行后面的表达式,由于++b是前置++,先自增后使用,++b的值为3,为真,并且逻辑或(&)具有短路的特点,只要一个为真就是着呢,后的表达式d++就不会执行。

        所以结果是:1 2 3 4

本次分享就到这里啦!

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

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

相关文章

Python爬虫(二):Requests库

所谓爬虫就是模拟客户端发送网络请求&#xff0c;获取网络响应&#xff0c;并按照一定的规则解析获取的数据并保存的程序。要说 Python 的爬虫必然绕不过 Requests 库。 1 简介 对于 Requests 库&#xff0c;官方文档是这么说的&#xff1a; Requests 唯一的一个非转基因的 P…

存储知识点:RAID0、RAID1、RAID5、RAID10特点是什么?所需的硬盘数量分别为多少?

RAID&#xff08;Redundant Array of Independent Disks&#xff09;是一种将多个独立的硬盘组合成一个逻辑磁盘的技术&#xff0c;目的是提高性能或容错能力。RAID有不同的级别&#xff0c;常见的有RAID0、RAID1、RAID5、RAID10等。下面我们来介绍这些级别的特点和所需的硬盘数…

套接字编程简介

作者&#xff1a;V7 博客&#xff1a;https://www.jvmstack.cn 一碗鸡汤 少年辛苦终身事&#xff0c;莫向光阴惰寸功。 —— 杜荀鹤 Socket概述 在计算机中产生和接受IO流的数据源是多种多样的&#xff0c;在网络编程中&#xff0c;有一个特殊的数据源就是socket。通俗点soc…

linux的系统日志

目录 一、日志文件的产生 二、日志文件存放在哪儿 &#xff08;1&#xff09;文本日志 &#xff08;2&#xff09;二进制日志 三、日志存放规则的配置文件 四、日志轮转 五、分析和监控日志 一、日志文件的产生 日志内容&#xff1a;内核、开机引导、守护进程启动运行的…

华为和思科两种常见的网络设备如何进行ospf配置?

概述 ospf&#xff08;开放最短路径优先&#xff09;是一种基于链路状态的动态路由协议&#xff0c;它可以在网络中自动发现和维护最优的路由路径。ospf广泛应用于大型和复杂的网络环境&#xff0c;因为它具有以下优点&#xff1a; 支持分层路由&#xff0c;可以将网络划分为…

WebAssembly黑暗的一面

案例1&#xff1a;技术支持诈骗 什么是技术支持诈骗&#xff1f; 技术支持诈骗是一种电话欺诈&#xff0c;其中诈骗者声称可以提供合法的技术支持服务。该骗局可能以陌生电话开始&#xff0c;骗子通常会声称来自合法的第三方的员工&#xff0c;如“微软”或“Windows部门”。他…

YOLOv5实现目标分类计数并显示在图像上

有同学后台私信我&#xff0c;想用YOLOv5实现目标的分类计数&#xff0c;因此本文将在之前目标计数博客的基础上添加一些代码&#xff0c;实现分类计数。阅读本文前请先看那篇博客&#xff0c;链接如下&#xff1a; YOLOv5实现目标计数_Albert_yeager的博客 1. 分类实现 以co…

web 实验一 HTML基本标签实验

实验原理 通过创建HTML5网页&#xff0c;验证form内多种元素标签及其属性的作用及意义。 实验目的 理解并掌握Form表单提交必须声明的内容 理解并掌握Input元素中多种类型属性的使用方法及使用场景 理解并掌握Label元素的使用方法 理解并掌握Datalist元素的使用方法 理解并掌握…

软件测试学习——笔记一

一、软件和软件测试 1、软件和软件分类 &#xff08;1&#xff09;软件&#xff1a;程序、数据、文档——用户手册 &#xff08;2&#xff09;软件的分类 按层次划分&#xff1a;系统软件、应用软件按组织划分&#xff1a;开源软件&#xff08;代码公开&#xff09;、商业软…

RSA 加密算法在C++中的实现 面向初学者(附代码)

概述 博文的一&#xff0c;二部分为基础知识的铺垫。分别从密码学&#xff0c;数论两个方面为理解RSA算法做好了准备。第三部分是对RSA加密过程的具体介绍&#xff0c;主要涉及其密钥对&#xff08;key-pair&#xff09;的获取。前三个部分与编程实践无关&#xff0c;可以当作…

C# | 内存池

内存池 文章目录 内存池前言什么是内存池内存池的优点内存池的缺点 实现思路示例代码结束语 前言 在上一篇文章中&#xff0c;我们介绍了对象池的概念和实现方式。对象池通过重复利用对象&#xff0c;避免了频繁地创建和销毁对象&#xff0c;提高了系统的性能和稳定性。 今天我…

你真的了解索引吗

当我们学习存储算法和索引算法时&#xff0c;他们可以深入了解如何在系统中存储和查询数据。因为存储和查询数据是许多系统的核心功能之一&#xff0c;例如数据库、搜索引擎等。理解这些算法可以帮助程序员更好地设计和优化系统架构&#xff0c;提高系统的可扩展性、可用性和性…

玩转Google开源C++单元测试框架Google Test系列(gtest)之二 - 断言

一、前言 这篇文章主要总结gtest中的所有断言相关的宏。 gtest中&#xff0c;断言的宏可以理解为分为两类&#xff0c;一类是ASSERT系列&#xff0c;一类是EXPECT系列。一个直观的解释就是&#xff1a; 1. ASSERT_* 系列的断言&#xff0c;当检查点失败时&#xff0c;退出当前…

大数据之光:Apache Spark 实用指南 大数据实战详解【上进小菜猪大数据】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 本文将深入探讨Apache Spark作为一种强大的大数据处理框架的基本概念、特点和应用。我们将详细介绍Spark的核心组件&#xff0c;包括Spark Core、Spark SQL、Spark Streaming和Spa…

百子作业 —— 中国邮递员问题

题目 严老师和宋老板去勘测武威市区的道路网&#xff0c;每一条路都需要勘测&#xff0c;且需要两人合作.武威市区可以近似地看成六横六纵组成的道路网&#xff0c;自西向东依次为学府路、民勤路、西关路、中关路、富民路、滨河路&#xff1b;自北向南依次为雷海路、宣武路、祁…

Redis基本数据类型及使用(2)

书接上回&#xff0c;这节讲讲其余的基本数据结构使用 集合&#xff0c;有序集合以及遍历和事务的使用 Set集合&#xff0c;无序不重复的成员 表现形式&#xff1a; key1string1string2key2string1string2 常用的基本操作&#xff1a; sadd key string1 [string2..]添加1…

第二十届宁波大学程序设计竞赛(同步赛)

A-0-1翻转_第二十届宁波大学程序设计竞赛&#xff08;同步赛&#xff09; (nowcoder.com) 思路&#xff1a; 我们观察发现&#xff0c;奇数位与偶数位的1每次操作一定时同时增加或者减少的&#xff0c;我们无法做到同时删除奇数位的两个1.。不满足相等则情况无解那么&#xf…

【谷粒商城之订单服务-支付】

本笔记内容为尚硅谷谷粒商城订单服务支付部分 目录 一、支付宝沙箱 沙箱环境 二、公钥、私钥、加密、加签、验签 1、公钥私钥 2、加密和数字签名 3、对称加密和非对称加密 三、内网穿透 四、整合支付 1、导入支付宝SDK依赖 2、封装工具类和PayVo 3、前端访问支付接…

python汉诺塔编程代码

汉诺塔问题是一个经典的递归问题。以下是使用Python实现汉诺塔的一个简单方法&#xff1a; python def hanoi(n, source, target, auxiliary): if n > 0: # 把 n-1 个盘子从 source 移动到 auxiliary hanoi(n-1, source, auxiliary, target) # 把第 n 个盘子从 source 移动到…

三十四、服务治理、实现负载均衡、

1、服务治理介绍 先来思考一个问题 通过上一章的操作&#xff0c;我们已经可以实现微服务之间的调用。但是我们把服务提供者的网络地址 &#xff08;ip&#xff0c;端口&#xff09;等硬编码到了代码中&#xff0c;这种做法存在许多问题&#xff1a; l 一旦服务提供者地址变化…