| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 初入C语言_6 -> 正文阅读 |
|
[C++知识库]初入C语言_6 |
我们之前可能已经介绍了一些C语言里的操作符,今天我们就这类知识来更深入一些的学习,我们知道加减乘除算是操作符,也是最常用的操作符,那除了这些还有什么呢?它们的使用方法和加减乘除又有什么不同呢?来看 一、操作符 C语言里的操作符大致可以分为这么几类:
我们来一一介绍:
算术操作符就是我们常说的加减乘除,算术嘛,数学当中只用这四个来计算可能99%的式子,不过在C语言当中还要多一个%,这个叫取模,它一般和/既分开又联合用,因为/一般用于两个int时,是取商,由于int只能表示整形,所以/直接省掉后面的余数,而%与/正好相反,可以说弥补了/的“不足”,%取的就是商之后的余数,15%10=5,290%100=90。其他的操作符相信不讲都明白,和数学是一样的。 注意:1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。 2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除 法。 3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
C语言当中还有一种叫做移位操作符,移位移位,说白了就是移动某个数的,那移什么位呢?怎么移呢?从你家移到我家吗?这里的移位操作符指的是移动某个数在内存中二进制数,我们知道int a=5;那么5在二进制中的表示方法00000000 00000000 00000000 00000101,由于int是4个字节大小,一个字节是8个比特位,所以整形定义的5二进制表示是0101,然后用0补全32位,移位操作符移动的正是这一串01,那么移位操作符怎么移动呢?来看代码:
注意,右移运算分两种:1. 逻辑移位 左边用0填充,右边丢弃 2. 算术移位 左边用原该值的符号位填充,右边丢弃。 那么如果说右移操作符最高位补,那么左移操作符呢?左边如果左移了右边并没有符号位,右边是构成我们所定义的数字的01啊,难道也补符号位吗,C语言规定如果左边抛弃了,右边自动补0。 ?大家应该可以发现左移操作符并没有右移操作符规定那么多,我们一般使用的话也是右移为主,所以这里着重给大家介绍的是右移。 警告? : 对于移位运算符,不要移动负数位,这个是标准未定义的。 例如:
完成了移位操作符后,我们知道了C语言的操作符原来大多都是以二进制码为主的,没错,二进制也是数据存在内存中的形式之一,所以C语言设计了很多针对二进制的位操作符,我们接下来介绍的这三个就是完全针对二进制位计算的。我们先来一段代码:
那么这段代码是什么意思呢?结果又如何呢?我们一起来画图分析一下: 我们知道二进制存储是以原码存储,打印补码,而原码取反-1转换成补码,补码+1取反得到原码,而这些规则只针对负数,整数的原反补在内存中是一样的,所以计算正数不需要考虑原反补的转换。 完成了这些学习后,我们来看一些练习题来加深一下印象吧:
大家在计算的时候会发现这道题的结果:a=20,b=10,结果正好相反,那么我们是否可以得出结论:异或操作是符合交换律的?是的,异或可以实现交换律,这样我们在回过头来看那一道交换两个数字的初级编程题,我们这下可以不创建临时变量就可以完成两个数字的交换了
这段代码不多讲,大家可以放到自己的编译器上测试一下,不过值得一提的是如何得到二进制中的1和0,可以采用移位操作符,也可以通过%2的方式,如果是奇数就会余1,偶数则余0。那如果不想一直循环%2有没有更好的方法呢?
这就用到了移位操作符,但是还是需要循环32次才能得到我的答案,思考一下还有没有更优解?
第三种方法只供参考,我们知道就可以了,一般这种方法难以想到。
int a=0;这样的语句我们已经不少写了,我们都知道这句代码的意思是将0赋值给a,这就是赋值操作符,千万不要和等于搞混,不要以为是a等于0,赋值操作语句应当从右往左看,应该是将0赋值给a,下面我们来看一些常见的赋值语句:
在这里提醒大家写代码时一定要注意代码风格,不要写的代码完全按照自己的习惯来,只有你自己能看懂,如果你用的是vs系列编译器,你会发现你在写代码时vs会自动注意一些空格的设置来让代码整体看起来更直观整齐,写赋值语句时不要连续赋值,不要吝啬回车,干嘛都挤在一行呢?也不要写a=b=5这样的语句,让别人看到了会说你外行的。
?这些就是C语言常见的赋值操作符,其作用就是为了让程序员写代码时有更方便地选择,比方说
这两个语句的作用其实是一样的,x+=10翻译过来就是x=x+10,其他的也以此类推,不过如果你记不清楚这些符合操作符的用法建议你还是一个一个写,其实都是自己的选择,并没有优劣之分。
?这里就时C语言很重要的单目操作符了,为什么叫单目呢?因为它只有一个,但是产生的作用是很大的,是C语言不可或缺的,我们来看代码:
取反(!)操作就是针对现有条件true或false取反面,比方说while(1)我们知道这将一直循环下去,因为while循环里的条件一直是真,如果我们写while(!1),这就将一次也不执行,因为如果学过java的小伙伴会知道boolean这个类型,它只能返回true或false,大于0为真小于0为假,1大于0为真,!1就为假,所以while判断的boolean返回值为false,所以一次也不执行。 sizeof我们上文提到过,我们直观的翻译能知道它是计算大小的操作符,它可以帮助我们计算数组的大小,类型的大小,只要有大小的它都可以计算,不过注意它和strlen可不一样,不要把它当作函数,strlen是正儿八经的字符串函数,但是sizeof只是一个操作符,我们接下来在来看一些sizeof关于数组的一些计算:
大家可以先自己计算一下四个表达式分别输出什么,第一个40第二个10相信大家已经没有问题了,4*10,1*10,如果还是不明白可以翻看上一篇博客,2和4可能造成了一些困难,我们先来看2,之前提到了数组传参只传数组的首元素地址,所以test1只获取到了arr[0]的地址,地址的大小和指针(后文会讲)都是一样的4字节,所以打印的是,这样4也就能讲通了,尽管传入的是char类型的数组是首元素地址,但是只要是地址它的大小都是4字节,所以4式打印的结果也是4。 接下来我们讲解++和--,也是来看代码:
注意++和--和+1 -1不同的是,变量本身真的会发生改变,如果你printf("%d\n",a-1);和printf("%d\n",b++);虽然输出的值是一样的,但是执行完这两条语句后a的值如何呢?a还是原来的值,因为你要打印的是a-1的结果,和a本身无关,但是b就会自增1,因为你是先让b++再打印它的值,两面都兼顾,所以在使用过程中要注意这两个操作的区别,++和--无论前置和后置都是对变量的自增,变量本身会发生改变。
?关系操作符,应该不用我多说了,和加减乘除一样的用法, 不过这里要注意的一点就是不要把==和=搞混了,在C语言当中=并不是等于,而是赋值,等于是==,判断等于的时候千万不要搞混。
大家发现逻辑操作符的这两个和刚刚的位操作符中的&和|有点像,不错,它们名字都差不多,前者叫与后者叫或,但是功能完全不一样,位操作符是针对二进制代码进行的计算,而这里的逻辑操作符明显根据名字可以知道是根据逻辑条件而生的,逻辑与即所判断的条件都为真才会执行,逻辑或即所判断条件只要有一条为真即为真。
我们来看一道练习题:
大家可以计算一下, 我们的目的就是为了了解逻辑与和逻辑或,当然不要研究的太深,会变得不幸。(会被绕进去) 这种代码一般不会出现次数很多,只是一些学校和公司作为题目出给学生用的, 因为这种代码没有任何营养,除了折磨人之外没有用处,那我们来看一下,答案就是1234,因为逻辑与要判断各条件的真假情况,a++,a是先使用后++,又因为是逻辑与操作,所以并不会进入后面的语句,所以bd压根就没有进行改变,然后打印时a确实完成了自增1,所以答案是1234,那后面的逻辑或呢?a也是先使用后++,但由于是或,所以会进入下一个条件,b为真,++后还是为真,但是或的特点是只要有一个为真就退出,所以d并没有计算,所以只有a和b进行了计算,所以答案是1334。
条件操作符也叫三目操作符,我们知道单目操作符,针对一个对象,那么三目也就是针对三个对象,这个操作符的意思就是表达式1大于表达式2吗?如果大于,表达式的返回值就为表达式2,如果不大于就返回表达式3的值,条件操作符实现的功能我们也可以用if else语句来实现:
逗号表达式在C语言当中用的不是很多,由于其像刚刚的很多前置后置++--一样必须需要人们很认真的来看,否则就会出错,所以使用率不高,但是我们也需要知道它,逗号表达式通常和括号来配合使用,就是用逗号隔开的多个表达式。,从左向右依次执行。整个表达式的结果是最 后一个表达式的结果。
由于使用次数实在有限,所以我们制作了解,不做深究。
?(1)[ ] 下标引用操作符 不难发现下标引用操作符就是我们用来拿取数组数值的操作符,它也只和数组配合使用。
(2)( ) 函数调用操作符 接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
括号想必不用过多介绍了,它在数学表达式中的作用也和现在相当,它的结合律最高,调用函数时也是不可或缺,承担形参的调用,具体做法如上。 (3)访问一个结构的成员 C语言当中有一种概念叫结构体,如果定义一个人的信息可能需要身高体重性别等等,那如何定义呢?C语言规定了结构体,它可以同时存入不同类型的数据,根据你的需求拿或放,当然我们的主要目的不是研究结构体,关于结构体我后期回传们开一篇博客来讲,我们主要来讲访问结构体的操作符:. 结构体.成员名 -> 结构体指针->成员名。
二、表达式求值表达式求值的顺序一部分是由操作符的优先级和结合性决定,同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型,我们接下里就来研究一下表达式中的优先级结合律。 加减乘除不用多说了,遵循数学的计算,在最初我介绍C语言时给过大家也一个操作符优先级,但是C语言当中存在着这样一种隐式类型转换,C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。 2.隐式类型转换 那么整形提升有什么意义呢?表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度 一般就是int的字节长度,同时也是CPU的通用寄存器的长度。 因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。 通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。
那么如何进行整形提升呢?整形提升是按照变量的数据类型的符号位来提升的。
3.算术转换 如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
4.操作符的属性 复杂表达式的求值有三个影响的因素。 1. 操作符的优先级 2. 操作符的结合性 3. 是否控制求值顺序。 两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。操作符优先级表见最初的博客。 再来看一段非法代码:
这段代码在不同的编译器中会有不同的结果,就是因为操作符的优先级在作祟 ?再来一段:
?这个代码有没有实际的问题? 有问题! 虽然在大多数的编译器上求得结果都是相同的,但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法, 再算减法,函数的调用先后顺序无法通过操作符的优先级确定。 来:
?看看同样的代码产生了不同的结果,这是为什么? 简单看一下汇编代码.就可以分析清楚. 这段代码中的第一个 + 在执行的时候,第三个++是否执行,这个是不确定的,因为依靠操作符的优先级 和结合性是无法决定第一个 + 和第三个前置 ++ 的先后顺序。 好了,先暂停一会儿,大家先消化一下,今天的编程博客先行告辞,下次见。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/29 4:23:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |