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

news2024/11/17 2:37:19

目录

一、操作符的分类

二、二进制和进制转换

        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);//13
	return 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,1
		printf("hehe\n");//打印hehe
	return 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、y
	return 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.coloradmin.cn/o/1665405.html

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

相关文章

【智能算法应用】基于果蝇算法-BP回归预测(FOA-BP)

目录 1.算法原理2.数学模型3.结果展示4.代码获取 1.算法原理 【智能算法应用】智能算法优化BP神经网络思路【智能算法】果蝇算法&#xff08;FOA&#xff09;原理及实现 2.数学模型 数据集样本特征数为13&#xff0c;适应度函数设计为&#xff1a; f i t n e s s e r r o…

skywalking的使用

文章目录 介绍概念介绍探针agent后台服务 使用后台界面查询异常接口查看访问量 遇到的问题 介绍 官网 https://skywalking.apache.org/ 安装包下载 https://skyapm.github.io/document-cn-translation-of-skywalking/ 组成 Agent&#xff08;探针&#xff09;&#xff1a;Ag…

UIKit之UIButton

功能需求&#xff1a; 点击按钮切换按钮的文字和背景图片&#xff0c;同时点击上下左右可以移动图片位置&#xff0c;点击加或减可以放大或缩小图片。 分析&#xff1a; 实现一个UIView的子类即可&#xff0c;该子类包含多个按钮。 实现步骤&#xff1a; 使用OC语言&#xf…

使用pandas的merge()和join()函数进行数据处理

目录 一、引言 二、pandas的merge()函数 基本用法 实战案例 三、pandas的join()函数 基本用法 实战案例 四、merge()与join()的比较与选择 使用场景&#xff1a; 灵活性&#xff1a; 选择建议&#xff1a; 五、进阶案例与代码 六、总结 一、引言 在数据分析和处理…

stata空间计量模型基础+检验命令LM检验、sem、门槛+arcgis画图

目录 怎么安装stata命令 3怎么使用已有的数据 4数据编辑器中查看数据 4怎么删除不要的列 4直接将字符型变量转化为数值型的命令 4改变字符长度 4描述分析 4取对数 5相关性分析 5单位根检验 5权重矩阵标准化 6计算泰尔指数 6做核密度图 7Moran’s I 指数 8空间计量模型 9LM检验…

Java | Leetcode Java题解之第68题文本左右对齐

题目&#xff1a; 题解&#xff1a; class Solution {private String line(List<String> list,int maxWidth,int totalLength,boolean isLast){StringBuilder sb new StringBuilder();sb.append(list.get(0));if(list.size() 1){String ap " ".repeat(maxW…

interview_bak

flink内存管理 JVM 存在的几个问题: Java 对象存储密度低。一个只包含 boolean 属性的对象占用了16个字节内存:对象头占了8个,boolean 属性占了1个,对齐填充占了7个。而实际上只需要一个bit(1/8字节)就够了。Full GC 会极大地影响性能,尤其是为了处理更大数据而开了很大…

Nest.js中使用任务调度

java中的xxl在nestJs中是有内置的任务调度nestjs/schedule npm install --save nestjs/schedule 在model中引入使用 在service中直接使用就行 具体间隔多久看官方配置 Task Scheduling | NestJS 中文文档 | NestJS 中文网

DDoS攻防,本质上是成本博弈!

在互联网里&#xff0c;分布式拒绝服务&#xff08;DDoS&#xff09;攻击作为一种常见的网络威胁&#xff0c;持续对网站、在线服务和企业基础设施构成严重挑战。本文旨在探讨实施DDoS攻击的大致成本、以及企业如何采取有效措施来防范此类攻击&#xff0c;确保业务连续性和网络…

二叉树进阶 --- 中

目录 1. find 的递归实现 2. insert 的递归实现 3. erase 的递归实现 3.1. 被删除的节点右孩子为空 3.2. 被删除的节点左孩子为空 3.3. 被删除的节点左右孩子都不为空 4. 析构函数的实现 5. copy constructor的实现 6. 赋值运算符重载 7. 搜索二叉树的完整实现 1. fi…

IM 是什么?

在当今数字化的时代&#xff0c;即时通讯&#xff08;IM&#xff09;已经渗透到人们的日常生活和企业的工作环境中。IM技术的快速i发展为人们提供了一种高效、便捷的沟通方式&#xff0c;不仅推动了社会的信息化进程&#xff0c;也提升了企业的协同效率和竞争力。 作为企业级I…

API接口调用|京东API接口|淘宝API接口

什么是电商API接口&#xff1a; 电商API接口是电商服务平台对外提供的一种接口服务&#xff0c;允许第三方开发者通过编程方式与电商系统进行数据交互和功能调用。 这些接口提供了一种标准化的方法来获取、更新或处理电商平台上的商品信息、订单状态、用户数据、支付信息、物流…

堆排序 之实现最小的K个数

目录 1、方式一&#xff1a;通过自定义实现建堆和堆化操作 2、方式二&#xff1a;借助模块heapq实现 2.1、模块heapq的基本使用 2.2、使用heapq实现最小的k个数 3、堆在实际项目的应用 实现语言&#xff1a;Python 3.9 题目来源&#xff1a;牛客 分析&#xff1a; 要找…

Offline: Overcoming Model Bias for Robust Offline Deep Reinforcement Learning

EAAI 2023 paper Intro model-free的离线强化学习由于价值函数估计问题存在训练的稳定性以及鲁棒性较低。本文提出基于模型的方法&#xff0c;同构构建稳定的动力学模型帮助策略的稳定训练。 method 本文基于模型的方法&#xff0c;所构造的转移模型输入状态动作&#xff0…

500元以内的蓝牙耳机品牌怎么选?五大优质品牌汇总

无论是通勤途中、学习间隙还是运动时&#xff0c;一款性能出众、价格亲民的蓝牙耳机都能为我们带来极致的听觉享受&#xff0c;然而面对市场上琳琅满目的品牌和型号&#xff0c;如何选择一款500元以内的优质蓝牙耳机&#xff0c;相信大家都会有这个难题&#xff0c;今天为了帮助…

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

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

Java里的String使用

1.Java WinForm项目 public static void main(String[] args) {String testString"22";String testString2"1096";String testString3"22";Student studentnew Student();student.Age"22";Test(student.Age);Test2(student.Age); }pu…

【吴恩达机器学习-week2】多个变量的特征缩放和学习率问题

特征缩放和学习率&#xff08;多变量&#xff09; 目标 利用上一个实验中开发的多变量例程在具有多个特征的数据集上运行梯度下降探索学习率对梯度下降的影响通过 Z 分数归一化进行特征缩放&#xff0c;提高梯度下降的性能 import numpy as np np.set_printoptions(precisio…

Appwrite 1.5 已在云端发布 - 四月产品更新

Hello, Appwriters&#x1f44b; 以下是四月份的产品更新和一个令人兴奋的消息&#xff1a; Appwrite 1.5 已在 Appwrite Cloud 上发布。这个版本备受期待&#xff0c;我们很高兴终于能与大家分享这个好消息。 为了让您快速复习&#xff0c;您现在可以开始使用云计算平台上的…

视频资源汇聚平台常见的几种接入方式

视频资源汇聚平台 视频汇聚平台可以实现海量资源的接入、汇聚、存储、处理、分析、运维等&#xff0c;平台具备轻量化接入能力&#xff0c;可支持多协议方式接入&#xff0c;包括主流标准协议GB28181、RTSP、ONVIF、RTMP、FLV、WEBSOCKET等&#xff0c;以及厂家私有协议与SDK接…