【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

说明:找表达式中各操作数的类型在上⾯这个列表中排名最靠前的类型,然后将所有不是该类型的操作数全都转换成该类型再进行表达式运算

十一、问题表达式

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.rhkb.cn/news/327510.html

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

相关文章

【Spring】初识 Spring AOP(面向切面编程)

目录 1、介绍AOP 1.1、AOP的定义 1.2、AOP的作用 1.3、AOP的核心概念及术语 2、AOP实现示例 3、EnableAspectJAutoProxy注解 1、介绍AOP 1.1、AOP的定义 AOP&#xff08;Aspect Orient Programming&#xff09;&#xff0c;直译过来就是面向切面编程&#xff0c;AOP 是一…

[动画详解]LeetCode151.翻转字符串里的单词

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到动画详解LeetCode算法系列 用通俗易懂的动画让算法题不再神秘 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成…

十二生肖Midjourney绘画大挑战:释放你的创意火花

随着AI艺术逐渐进入大众视野&#xff0c;使用Midjourney绘制十二生肖不仅能够激发我们的想象力&#xff0c;还能让我们与传统文化进行一场新式的对话。在这里&#xff0c;我们会逐一提供给你创意满满的绘画提示词&#xff0c;让你的作品别具一格。而且&#xff0c;我们还精选了…

Python进行excel处理-01

最近干采购&#xff0c;每个月要对供应商的对账单&#xff0c;对对应的采购订单号和物料编号的价格和数量&#xff0c;是不是和物料管控总表里面的价格数量是不是一致&#xff0c;于是写了一个代码。 从总表里面找到&#xff0c;对账单里对应采购订单和物料编码的数据&#xf…

vscode 通过ssh 远程执行ipynb +可以切换conda env

主要是保证几个点 远程服务器python 环境没问题 conda这些也都有的ssh的账户 是有conda权限的没有免密就输入密码 免密教程就是最基本的那种 公钥copy过去就行了vscode 那几个插件都要装好 开始操作 首先 vscode 点击左侧工具栏中的扩展&#xff0c;搜索“ssh”&#xff0c;…

计算机vcruntime140.dll找不到如何修复,分享5种靠谱的修复教程

当您在运行某个应用程序或游戏时遇到提示“找不到vcruntime140.dll”&#xff0c;这通常意味着系统中缺少了Visual C Redistributable for Visual Studio 2015或更高版本的一个重要组件。这个错误通常发生在运行某些程序时&#xff0c;系统无法找到所需的动态链接库文件。小编将…

(四十二)第 6 章 树和二叉树(树的二叉链表(孩子-兄弟)存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

15-ps命令

常用选项 aux axjf a&#xff1a;显示一个终端所有的进程u&#xff1a;显示进程的归属用户及内存使用情况x&#xff1a;显示没有关联控制终端j&#xff1a;显示进程归属的进程组idf&#xff1a;以ASCII码的形式显示出进程的层次关系 ps aux其中| more是只显示一部分内容&…

【实战】算法思路总结

面试过程中&#xff0c;总是被拷打&#xff0c;信心都要没了。但是也慢慢摸索出一些思路&#xff0c;希望对大家有帮助。 &#xff08;需要多用一下ACM模式&#xff0c;力扣模式提供好了模板&#xff0c;自己在IDEA里面写的话&#xff0c;还是会有些陌生&#xff09; 0、基本…

Edge(微软)——一款充满创新精神的浏览器

随着科技的不断进步&#xff0c;互联网浏览器已经成为我们日常生活中不可或缺的工具。在这个领域&#xff0c;微软Edge作为一款新型的浏览器&#xff0c;凭借其独特的功能和优秀的性能&#xff0c;逐渐在市场上占据了一席之地。本文将深入探索微软Edge的特点、优势以及它如何改…

Acrobat Pro DC 2023 for Mac:PDF处理的终极解决方案

Acrobat Pro DC 2023 for Mac为Mac用户提供了PDF处理的终极解决方案。它具备强大的文档处理能力&#xff0c;无论是查看、编辑还是创建PDF文件&#xff0c;都能轻松胜任。在编辑功能方面&#xff0c;Acrobat Pro DC 2023支持对文本、图像进行精准的修改和调整&#xff0c;还能添…

一台linux通过另一台linux访问互联网-TinyProxy

参考&#xff1a; https://blog.csdn.net/weixin_41831919/article/details/113061317https://www.yuncongz.com/archives/1.htmlhttps://blog.csdn.net/aoc68397/article/details/101893369 环境&#xff1a;ubuntu 18.04 机器1: IP 219.216.65.252 (可以访问外网) 机器2: IP…

廉洁教育vr虚拟全景展览馆成为社会普法的重要基石

廉政教育是社会文明的重要基石&#xff0c;也是我们每个人的责任与担当。在这个数字化、信息化的新时代&#xff0c;我们特别推出廉政3D线上数字展厅&#xff0c;为公众打造一个沉浸式、互动式的廉政教育新平台。 走进廉政3D线上数字展厅&#xff0c;就如同置身于一个充满智慧与…

[笔试训练](二十二)064:添加字符065:数组变换066:装箱问题

目录 064:添加字符 065:数组变换 066:装箱问题 064:添加字符 添加字符_牛客笔试题_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 枚举所有A&#xff0c;B字符串可能的对应位置&#xff0c;得出对应位置不同字符数量的最小情况 两字符串的字符数量差n-m&…

Keil编程不同驱动文件引用同一个常量的处理方法

基础不牢&#xff0c;地动山摇&#xff0c;最近单片机编程又遇到一个基础问题。 我在头文件中定义了一个常量同时给两个驱动文件使用&#xff0c;封装的时候编译没问题&#xff0c;但是在main函数中引用驱动函数的时候就出现了重定义的问题&#xff0c;如下如所示。 解决方法很…

搜索引擎的设计与实现(三)

目录 5 系统详细实现 5.1实现环境配置 5.2功能实现 5.2.1 建立索引 5.2.2 文件搜索实现 5.2.3 数据库的连接配置 5.2.4 数据库搜索实现 5.2.5 后台数据编辑实现 前面内容请移步 搜索引擎的设计与实现&#xff08;二&#xff09; 免费源代码&毕业设计论文 搜索…

Linux学习笔记1---Windows上运行Linux

在正点原子的教程中学习linux需要安装虚拟机或者在电脑上安装一个Ubuntu系统&#xff0c;但个人觉得太麻烦了&#xff0c;现在linux之父加入了微软&#xff0c;因此在Windows上也可以运行linux 了。具体方法如下&#xff1a; 一、 在Windows上的设置 在window的搜索框内&#…

Java的类和对象(一)—— 初始类和对象,this关键字,构造方法

前言 从这篇文章开始&#xff0c;我们就进入到了JavaSE的核心部分。这篇文章是Java类和对象的第一篇&#xff0c;主要介绍类和对象的概念&#xff0c;this关键字以及构造方法~~ 什么是类&#xff1f;什么是对象&#xff1f; 学过C语言的老铁们&#xff0c;可以类比struct自定义…

GPT-4o,AI实时视频通话丝滑如人类,Plus功能免费可用

不开玩笑&#xff0c;电影《她》真的来了。 OpenAI最新旗舰大模型GPT-4o&#xff0c;不仅免费可用&#xff0c;能力更是横跨听、看、说&#xff0c;丝滑流畅毫无延迟&#xff0c;就像在打一个视频电话。 现场直播的效果更是炸裂&#xff1a; 它能感受到你的呼吸节奏&#xf…

鸿蒙ArkUI开发:常用布局【相对布局】

相对布局&#xff08;RelativeContainer&#xff09; 相对布局可以让子元素指定兄弟元素或父容器作为锚点&#xff0c;基于锚点做位置布局必须为RelativeContainer及其子元素设置ID&#xff0c;用于指定锚点信息。未设置ID的子元素不会显示RelativeContainer ID为“__containe…