【C语言】/*操作符(下)*/

目录

一、操作符的分类

二、二进制和进制转换

        2.1 进制

        2.2 进制之间的转换

三、原码、反码、补码

四、单目操作符

五、逗号表达式

六、下标引用操作符[]

七、函数调用操作符()

八、结构体成员访问操作符

        8.1 直接访问操作符(.)

        8.2 间接访问操作符(->)

九、操作符的属性:优先级、结合性

        9.1 优先级

        9.2 结合性 

十、表达式求值

        10.1 整型提升

        10.2 算数转换

十一、问题表达式

        11.1 示例1

                 11.2 示例2

        11.3 示例3

        11.4 示例4

        11.5 总结 


一、操作符的分类

算术操作符: + 、- 、* 、/ 、%

移位操作符: <<、>>

位操作符: &、|、^

赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= <<= 、>>=、&= 、|= 、^=

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

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

逻辑操作符: && 、||

条件操作符: ?  :

逗号表达式:

下标引⽤: [] 

函数调⽤: () 

结构成员访问:->

二、二进制和进制转换

2.1 进制

1. 其实我们经常能听到2进制、8进制、10进制、16进制这样的讲法,那是什么意思呢?其实2进制、8进制、10进制、16进制是数值的不同表⽰形式⽽已

2. 数值15的各种进制的表⽰形式:

    15的2进制:1111

    15的8进制:17

    15的10进制:15

    15的16进制:F

3. 

4. 二进制的每一位只能是:0~1(满2进1)

    八进制的每一位只能是:0~7(数字描述八进制会以0开头)

    十进制的每一位只能是:0~9

    十六进制的每一位只能是:0~9,A~F/a~f (数字描述十六进制会以0x/0X开头)

2.2 进制之间的转换

1. 2进制转10进制:2进制的每⼀位的权重,从右向左是: 2^0 , 2^1 , 2^3 ... 要计算一个二进制的十进制表示形式是多少,按如下图所示的方法计算即可 (二进制的每一位乘以对应权重再加起来即可)。

2. 10进制转2进制:(让10进制数除2直到余数是0/1为止,再从下至上取余数即可)

3. 2进制转8进制:(将二进制从右向左3个3个划分为一组,不够的补0,每三个二进制数经过转换后就是一个8进制数,转换的方法如下图,每三个二进制位分别乘以421加起来就是转换的一个八进制位)

4. 2进制转16进制:(将二进制从右向左4个4个划分为一组,不够的补0,每四个二进制数经过转换后就是一个16进制数,转换的方法如下图,每四个二进制位分别乘以8421加起来就是转换的一个16进制位)

三、原码、反码、补码

1. 整数的2进制表⽰⽅法有三种,即原码、反码和补码。

2. 有符号整数的三种表⽰⽅法均有符号位和数值位两部分2进制序列中,最⾼位的1位是被当做符号位,剩余的都是数值位,符号位⽤0表⽰“正”,⽤1表⽰“负”

3. 正整数的原、反、补码都相同

4. 负整数的三种表⽰⽅法各不相同

5. 原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。

    反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

    补码:反码+1就得到补码。

6. 例如:-10存放在整型变量a中,即用4字节来存放整型-10

    原码:10000000 00000000 00000000 00001010

    反码:111111111 111111111 111111111 111110101

    补码:111111111 111111111 111111111 111110110

6. 补码得到原码也是可以使⽤:符号位不变,其他位按位取反,+1的操作。

7. 对于整形来说:整型数据存放内存中存放的是补码,在计算的时候也是用补码来计算的,为什么呢?

    答:在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀ 处理;同时,加法和减法也可以统⼀处理(CPU只有加法器),此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

四、单目操作符

1. 单⽬操作符: !、++、--、&*、+、-~ sizeof、(类型)

2. 单⽬操作符的特点是只有⼀个操作数。

3. 单目操作符&,名为取地址操作符,利用它就可以得到一个变量的地址,用printf打印地址时,用占位符%p(%p是以16进制形式打印地址,一个16进制位表示4个二进制位,例如,0x00AFF760用二进制表示为0000 0000 1010 1111 1111 0111 0110 0000);取地址得到的地址是变量开辟的所有内存单元中的最低的地址,因为知道最低的地址,变量所开辟的其他内存单元的地址顺藤摸瓜就能找到。

4. 单目操作符*,名为解引用操作符,它的操作数通常为一个指针变量,如果想要通过指针变量中的地址找到地址所指向的变量,可以通过对指针变量解引用就能找到,例如:int a = 10; int* pa = &a; 这两句代码中如果对变量pa进制解引用,则*pa就是变量a,对*pa赋值相当于对变量a赋值。

5. 单目操作符~,名为按位取反操作符,它的操作数必须是整型,对0按位取反的结果是-1

6. 温馨提示:橙色部分的单目操作符在【C语言】/*操作符(上)*/-CSDN博客 中已经讲解过了。

五、逗号表达式

1. 逗号表达式的语法形式:exp1, exp2, exp3, …expN (就是用逗号隔开的多个表达式)

2. 特点:从左向右依次执⾏,整个表达式的结果是最后⼀个表达式的结果。( 注意每个表达式都会计算哦!!!)

3. 示例1:下列为伪代码

        a = get_val();
        count_val(a);
        while (a > 0)
        {
                    //业务处理
                    a = get_val();
                    count_val(a);
        }

4. 上面的伪代码,我们会发现第1、2行和6、7行这样写会有些冗余,学习完逗号表达式后,我们可以将代码改进为:

    while (a = get_val(), count_val(a), a>0) 

    { 

             //业务处理

    }

//示例2:
#include <stdio.h>
int main()
{int a = 1;int b = 2;int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式//         0        12      12      13    printf("c = %d\n", c);//13return 0;
}
//示例3:
#include <stdio.h>
int main()
{int a = 1;int b = 2;int c = 3; int d = 4;if (a = b + 1, c = a / 2, d > 0)//a=3,c=1,1printf("hehe\n");//打印hehereturn 0;
}

六、下标引用操作符[]

1. 下标引用操作符[]有两个操作数

2. 语法形式:⼀个数组名[⼀个索引值]

3. 例如:

    int arr[10];//创建数组

   arr[9] = 10;//使用下标引⽤操作符访问数组元素,[ ]的两个操作数是arr和9

七、函数调用操作符()

1. 函数调用操作符()可以接受⼀个或者多个操作数,第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。(函数调用操作符最少有一个操作数)

2. 函数调用时:Add(x, y);//这里的()就是函数调用操作符

    函数定义时:void Mul(int x, int y);//这里的()是函数调用操作符

    函数声明时:extern Sub(int x, int y);//这里的()也是函数调用操作符

八、结构体成员访问操作符

8.1 直接访问操作符(.)

1. 使用场景:当我们知道结构体变量名时,想要找到它的成员变量,可以对结构体变量使用直接访问操作符(.)来找到它的成员变量。

2. 语法形式:结构体变量.成员名

3. 举例:如下图代码

#include <stdio.h>
struct Point
{int x;int y;
} p = { 1,2 };int main()
{printf("x: %d\ny: %d\n", p.x, p.y);//使用(.)找到p中的成员变量return 0;
}

8.2 间接访问操作符(->)

1. 使用场景:当我们只知道存放着结构体变量地址的指针变量时,想要找到该指针变量中地址所指向的结构体变量的成员变量,可以对该指针变量使用间接访问操作符(->)来找到成员变量。

2. 语法形式:结构体指针->成员名

3. 举例:如下图代码

#include <stdio.h>
struct Point
{int x;int y;
};
int main()
{struct Point p = { 3, 4 };struct Point* ptr = &p;ptr->x = 10;ptr->y = 20;printf("x = %d\ny = %d\n", ptr->x, ptr->y);//相当于ptr找到它所指向的p的成员x、yreturn 0;
}

九、操作符的属性:优先级、结合性

操作符的优先级和结合性决定了表达式求值的计算顺序

9.1 优先级

1. 概念:优先级讨论的是,如果⼀个表达式包含多个操作符,哪个操作符应该优先执⾏的问题。

2. 例如表达式 3 + 4 * 5 ⾥⾯既有加法操作符( + ),⼜有乘法操作符( * ),由于乘法的优先级⾼于加法,所以会先计算 4 * 5 ,⽽不是先计算 3 + 4 。

3. 优先级起作用的条件:对象:相邻操作符,效果:优先级高的先执行

4. 由于圆括号的优先级最高,因此在实际应用过程中可以使用它改变其他操作符的优先级

9.2 结合性 

1. 概念:如果两个操作符优先级相同,优先级是没办法确定先计算哪个得,这时候就得看结合性,根据操作符是左结合,还是右结合,决定执⾏顺序。⼤部分操作符是左结合(从左向右执⾏),少数运算符是右结合(从右向左执⾏),⽐如赋值运算符( = )。

2. 例如表达式5 * 6 / 2里面 * 和 / 的优先级相同,它们都是左结合运算符,所以从左到右执⾏,先计算 5 * 6 , 再计算 6 / 2 。

3.  各操作符优先级和结合性的官方参考:C 运算符优先级 - cppreference.com

十、表达式求值

10.1 整型提升

1. 概念:C语⾔中整型算术运算总是⾄少以默认整型类型int的精度来进⾏运算的,为了获得这个精度,表达式中的字符和短整型操作数在使⽤之前会被转换为普通整型,这种转换称为整型提升。(注意:整型提升针对的是整型)

2. 整型提升的意义: 表达式的整型运算要在CPU的相应运算器件内执⾏,CPU内整型运算器的操作数的字节⻓度⼀般就是int的字节⻓度,同时也是CPU的通⽤寄存器的⻓度。 因此,即使两个char类型的相加,在CPU执⾏时实际上也要先转换为CPU内整型操作数的标准⻓度。 通⽤CPU是难以直接实现两个8⽐特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种⻓度可能⼩于int⻓度的整型值,都必须先转换为int或unsigned int,然后才能送⼊CPU去执⾏运算。

3. //实例1

    char a,b,c;

    ...

   a = b + c;

4. 上面示例中b和c的值被提升为普通整型,然后再执⾏加法运算,加法运算完成之后,结果将被截断,然后再存储于a中。

5. 如何进⾏整体提升呢?

    ① 有符号整数提升按照符号位来提升。

    ② ⽆符号整数提升,⾼位补0。

6. //负数的整形提升

    char c1 = -1;

    变量c1的⼆进制位(补码)中只有8个⽐特位:

    1111111

    因为 char 为有符号的 char

    所以整形提升的时候,⾼位补充符号位,即为1

    提升之后的结果是: 11111111 11111111 11111111 11111111

7. //正数的整形提升

    char c2 = 1;

    变量c2的⼆进制位(补码)中只有8个⽐特位:

    00000001

    因为 char 为有符号的 char

    所以整形提升的时候,⾼位补充符号位,即为0

    提升之后的结果是: 00000000 00000000 00000000 00000001

10.2 算数转换

1. 如果某个操作符的各个操作数属于不同的类型,那么除⾮其中⼀个操作数的转换为另⼀个操作数的类型,否则操作就⽆法进⾏

2. 下⾯的层次体系称为寻常算术转换。

     long double

     double

     float

     unsigned long int

     long int

     unsigned int

     int

3. 如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算

十一、问题表达式

11.1 示例1

1. //表达式的求值部分由操作符的优先级决定

    //表达式1

  a*b + c*d + e*f

2. 表达式1在计算的时候,由于 * ⽐ + 的优先级⾼,只能保证, * 的计算是⽐ + 早,但是优先级并不能决定第三个 * ⽐第⼀个 + 早执⾏

3. 所以即使我们知道了优先级和结合性,也未必能准确得出表达式的计算顺序,它可能不具有唯一性,当表达式中的a、b、c、d、e、f不是单纯的数值而是表达式时,可想而知在不具有唯一性的表达式中,计算的结果可能是有所差异的。

4. 解决方法,不要写有连续几个操作符的表达式,把复杂的计算尽量拆开去写;或者在复杂的表达式中用()来明确表示哪个先算,哪个后算

11.2 示例2

1. //表达式2

    c + --c;

2. 上面的表达式中,操作符的优先级只能决定⾃减 -- 的运算在 + 的运算的前⾯,但是我们并没有办法得知, + 操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。(例如,c原本为5,--c后c为4,但我们无法判断,第一个c是将5带入表达式,还是将4带入表达式。如果要修改,可以写成c + (--c),这样写会默认+ 的左操作数的获取在右操作数之后。)

11.3 示例3

1. //表达式3

    int main()

    {

            int i = 10;

            i = i-- - --i * ( i = -3 ) * i++ + ++i; printf("i = %d\n", i);

            return 0;

    }

2. 表达式3在不同编译器中测试结果:

3. 这个示例也说明了不同的编译器对复杂表达式的解读方式是有差异的。

11.4 示例4

#include <sdtio.h>
int fun()
{static int count = 1;return ++count;
}int main()
{int answer;answer = fun() - fun() * fun();printf( "%d\n", answer);//输出多少?return 0;
}

1. 虽然在⼤多数的编译器上求得结果都是相同的,但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法,再算减法。 函数的调⽤先后顺序⽆法通过操作符的优先级确定,answer = fun() - fun() * fun()可能是 2-3*4 也可能是 3-4*2 等。

11.5 总结 

1. 即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯⼀的计算路径,那这个表达式就是存在潜在⻛险的,建议不要写出特别负责的表达式。

本篇文章已完结,谢谢支持哟 ^^ !!!

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

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

相关文章

修改el-checkbox样式

一定要在最外层&#xff1b; //未选中框/deep/ .el-checkbox__inner{border-color: #0862a3;}//选中框/deep/ .el-checkbox__input.is-checked .el-checkbox__inner{background-color: #0862a3;border-color: #0862a3;}//未选中框时右侧文字/deep/ .el-checkbox__label{}//选中…

git 推送github 选https遇到登录 openSSH问题

使用https需要使用github令牌token作为密码&#xff0c; 使用SSH不需要登录。 还有一个问题&#xff1a; 创建github仓库后没有quick setup页面解决办法 千万不要点击任何多的操作&#xff01;&#xff01;&#xff01;输入仓库名&#xff0c;直接create&#xff01;&#x…

return语句

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 return语句 一、return语句后面跟表达式二、return无返回三、return返回的值和函数返回类型不一致四、return语句执行后,后方仍然存在代码五、存在分支语句&#xff0c;需考虑…

去哪里找高清视频素材?推荐几个短视频素材免费网站

在数字时代&#xff0c;视频内容的质量直接影响观众的吸引力和留存率。尤其是高清、4K视频素材和可商用素材&#xff0c;它们在提升视觉质量和叙事深度方面起到了至关重要的作用。以下是一些国内外的顶级视频素材网站&#xff0c;它们提供的资源将为您的创作提供极大的支持和灵…

LeetCode/NowCoder-链表经典算法OJ练习1

目录 说在前面 题目一&#xff1a;移除链表元素 题目二&#xff1a;反转链表 题目三&#xff1a;合并两个有序链表 题目四&#xff1a;链表的中间节点 SUMUP结尾 说在前面 dear朋友们大家好&#xff01;&#x1f496;&#x1f496;&#x1f496;数据结构的学习离不开刷题…

机器人系统仿真

0、何为仿真 通过计算机对实体机器人系统进行模拟的技术。 1、为何仿真 低成本&#xff1a; 机器人实体一般价格昂贵&#xff0c;为降低机器人学习、调试的成本&#xff1b;高效&#xff1a; 搭建的环境更为多样且灵活&#xff0c;可以提高测试效率以及测试覆盖率&#xff1b…

三大消息传递机制区别与联系

目录 总结放开头 1、定义区别&#xff1a; EventBus Broadcast Receiver Notification 2、使用区别: EventBus Broadcast Receiver Notification 3、补充通知渠道&#xff1a; 通知渠道重要程度 总结放开头 BroadCast Receiver:属于安卓全局监听机制&#xff0c;接收…

【算法】最短路问题 bfs 到 dijkstra

1976、到达目的地的方案数 你在一个城市里&#xff0c;城市由 n 个路口组成&#xff0c;路口编号为 0 到 n - 1 &#xff0c;某些路口之间有 双向 道路。输入保证你可以从任意路口出发到达其他任意路口&#xff0c;且任意两个路口之间最多有一条路。 给你一个整数 n 和二维整…

五一 大项目--docker-compose编排lnmp完成wordpress

Docker 中的 Nginx 服务为什么要启用 HTTPS 一安装容器 1 安装docker-20.10.17 2 安装所需的依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm23 添加Docker官方仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos…

Linux-线程概念

1. 线程概念 线程&#xff1a;轻量级进程&#xff0c;在进程内部执行&#xff0c;是OS调度的基本单位&#xff1b;进程内部线程共用同一个地址空间&#xff0c;同一个页表&#xff0c;以及内存中的代码和数据&#xff0c;这些资源对于线程来说都是共享的资源 进程&#xff1a;…

RabbitMQ (windows) 安装

大家好我是苏麟 , 今天安装一下 RabbitMQ . 官网 : RabbitMQ: One broker to queue them all | RabbitMQ 1.点击 Getting Started 2. 点击 Docs 3.点击 Install And Upgrade 4.点击 installation via Chocolatory 5. 直接下载安装包 RabbitMQ 下好了先放在一遍 RabbitMQ 需要 E…

【C++】-------反向迭代器的模拟实现(补充)

目录 前言 一、反向迭代器接口&#xff08;用户层&#xff09; 二、模拟实现 三、以vector模拟实现为例 四、总结 前言 在vector和list的接口中我们实际上有说明过反向迭代器的用法&#xff0c;这里就有个问题&#xff0c;并不是只有这两个容器存在反向迭代器的。那么对于他…

点云DBSCAN聚类,同时获取最多点数量的类,同时删除其他的类并显示

代码的主要目的是处理一个点云文件(从某个巷道或类似环境中获取的),并尝试识别并可视化其中的主要结构(比如墙壁),同时去除可能的噪声和异常点。它首先读取一个点云文件,进行降采样和异常点移除,然后使用DBSCAN聚类算法对剩余的点云进行聚类,最后选择并可视化包含最多…

应用案例 | 商业电气承包商借助Softing NetXpert XG2节省网络验证时间

一家提供全方位服务的电气承包商通过使用Softing NetXpert XG2顺利完成了此次工作任务——简化了故障排查的同时&#xff0c;还在很大程度上减少了不必要的售后回访。 对已经安装好的光纤或铜缆以太网网络进行认证测试可能会面临不同的挑战&#xff0c;这具体取决于网络的规模、…

示例五、气敏传感器

通过以下几个示例来具体展开学习,了解气敏传感器原理及特性&#xff0c;学习气敏传感器的应用&#xff1a; 示例五、气敏传感器 一、基本原理&#xff1a;随着人们生活水平的不断提高&#xff0c;人们对环境和健康问题越来越重视。各种燃气的广泛使用&#xff0c;使生产效率和…

多模态CLIP和BLIP

一、CLIP 全称为Contrastive Language-Image Pre-Training用于做图-文匹配&#xff0c;部署在预训练阶段&#xff0c;最终理解为图像分类器。 1.背景 以前进行分类模型时&#xff0c;存在类别固定和训练时要进行标注。因此面对这两个问题提出CLIP&#xff0c;通过这个预训练…

B 站评论系统架构设计难点

更多大厂面试内容可见 -> http://11come.cn B 站评论系统架构设计难点 这里整理一下在哔哩哔哩技术公众号看到的 B 站评论系统的架构设计文章&#xff0c;自己在学习过程中&#xff0c;对其中感觉比较有帮助的点做一下整理&#xff0c;方便以后查阅&#xff0c;详细版可以点…

Portforge:一款功能强大的轻量级端口混淆工具

关于Portforge Portforge是一款功能强大的轻量级端口混淆工具&#xff0c;该工具使用Crystal语言开发&#xff0c;可以帮助广大研究人员防止网络映射&#xff0c;这样一来&#xff0c;他人就无法查看到你设备正在运行&#xff08;或没有运行&#xff09;的服务和程序了。简而言…

邂逅Linux--常见指令,万物为文件(一)

引子&#xff1a;在之前&#xff0c;我们经常听到Linux&#xff0c;那什么是Linux呢&#xff1f;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布&#xff…

力扣每日一题-统计已测试设备-2024.5.10

力扣题目&#xff1a;统计已测试设备 题目链接: 2960.统计已测试设备 题目描述 代码思路 根据题目内容&#xff0c;第一感是根据题目模拟整个过程&#xff0c;在每一步中修改所有设备的电量百分比。但稍加思索&#xff0c;发现可以利用已测试设备的数量作为需要减少的设备电…