第四章 表达式《C语言程序设计现代方法(第2版)》读书笔记

简介: 第四章 表达式《C语言程序设计现代方法(第2版)》读书笔记

第四章 表达式🚀


  1.  算术运算符,包括加、减、乘和除。
  2.  关系运算符进行诸如“i0大”这样的比较运算。
  3.  逻辑运算符实现诸如“i0大并且i10小”这样的关系运算。


4.1 算术运算符🚀


image.png


一元运算符 + 什么都不做;实际上,经典 C中甚至不存在这种运算符。它主要用于强调某数值常量是正的。

除%运算符以外,表4-1中的二元运算符既允许操作数是整数也允许操作数是浮点数,两者混合也是可以的。 当把int 型操作数和 float 型操作数混合在一起时,运算结果是 float型的。因此,9+2.5f 的值为 11.5 ,而 6.7f/2 的值为 3.35 。




运算符/和运算符%需要特别注意以下几点。


1.运算符 / 可能产生意外的结果。 当两个操作数都是整数时 ,运算符 / 会丢掉分数部分来“截

取”结果。因此, 1 / 2 的结果是 0 而不是 0.5 。

2.运算符%要求操作数是整数。 如果两个操作数中有一个不是整数,程序将无法编译通过。

3. 把零用作/或%的右操作数会导致未定义的行为 ( 4.4 节)。

4. 当运算符/和运算符%用于负操作数时,其结果难以确定。 根据 C89 标准,如果两个

操作数中有一个为负数,那么除法的结果既可以向上取整也可以向下取整。(例如, -9/7

的结果既可以是- 1 也可以是- 2 。)在 C89 中,如果 i 或者 j 是负数, i%j 的符号与具体实现

有关。(例如, -9%7 的值可能是- 2 或者 5 。) 但是在C99中,除法的结果总是向零截取的(因此-9/7的结果是-1),i%j的值的符号与i的相同(因此-9%7的值是-2)。


                                               “由实现定义”的行为  


       术语 由实现定义 ( implementation-defined )出现频率很高,因此值得花些时间讨论一下。 C 标准故意对C语言的部分内容未加指定,并认为其细节可以由“实现”来具体定义。所谓实现是指程序在特定的平台上编译、链接和执行所需要的软件。 因此,根据实现的不同,程序的行为可能会稍有差异。C89中运算符 / 和运算符 % 对负操作数的行为就是一个由实现定义行为的例子。

       留下语言的一部分内容未加指定看起来可能有点奇怪,甚至很危险,但这正反映了C 语言的基本理念。 C语言的目标之一是高效,这常常意味着要与硬件行为相匹配。- 9 除以 7 时,有些CPU产生的结果是- 1 ,有些为- 2 。 C89 标准简单地反映了这一现实。

       最好避免编写依赖于由实现定义的行为的程序。如果不可能做到,起码要仔细查阅手册—— C标准要求在文档中说明由实现定义的行为。


运算符的优先级和结合性


image.png


4.2 赋值运算符🚀


4.2.1 简单赋值🚀

表达式v = e的赋值效果是求出表达式e的值,并把此值复制给v

如果ve的类型不同,那么赋值运算发生时会把e的值转化为v的类型:


image.png


注意:


注意由于存在类型转换,串在一起的赋值运算的最终结果可能不是预期的结果:

int i;

float f;

f = i = 33.3f;

首先把数值 33 赋值给变量 i ,然后把 33.0 (而不是预期的 33.3 )赋值给变量 f 。


4.2.2 左值🚀


image.png


4.3 自增运算符和自减运算符🚀


++i意味着“立即自增i”,而i++则意味着“现在先用i的原始值,稍后 再自增i”。这个“稍后”有多久呢? C语言标准没有给出精确的时间,但是可以放心地假 设i将在下一条语句执行前进行自增。


需要记住的是,后缀 ++ 和后缀 -- 比一元的正号、负号优先级高,而且都是左结合的。前缀

++ 和前缀 -- 与一元的正号、负号优先级相同,而且都是右结合的。


4.4 表达式求值

(最高优先级为1,最低优先级为5),最后一列显示了每种运算符的结合性。


image.png


      根据C 标准,类似 c = (b = a + 2) – (a = 1); 和 j = i * i++; 这样的语句都会导致“未定义的行为”(undefined behavior ),这跟 4.1节中讲的由实现定义的行为是不同的。当程序中出现未定义的行为时,后果是不可预料的。不同的编译器给出的编译结果可能是不同的,但这还不是唯一可能发生的事情:首先程序可能无法通过编译,就算通过了编译也可能无法运行,就

算可以运行也有可能崩溃、不稳定或者产生无意义的结果。换句话说,应该像躲避瘟疫一样避免未定义的行为。


4.5 表达式语句🚀

C语言有一条不同寻常的规则,那就是任何表达式都可以用作语句。换句话说,不论表达

式是什么类型,计算什么结果,我们都可以通过在后面添加分号的方式将其转换成语句。例如,可以把表达式++i转换成语句

++i;

键盘上的误操作很容易造成“什么也不做”的表达式语句。例如,本想输入

i = j;

但是却错误地输入

i + j;

(因为 = 和 + 两个字符通常在键盘的同一个键上,所以这种错误发生的频率可能会超出

想象。)某些编译器 可能会检查出无意义的表达式语句 ,会显示类似“ statement with no

effect ”的警告。


问与答🚀

问:我注意到C语言没有指数运算符。如何求一个数的幂呢?

答:通过重复乘法运算的方法可以进行整数的较低的整数次幂运算( i * i * i  i的立方运算)。如果想计算  整数次幂,可以调用pow函数( 23.3 节)。(abs()绝对值)


问:我想把%运算符用于浮点数,但程序无法通过编译。该怎么办?p.37

答:%运算符要求操作数是整数,可以试试fmod函数( 23.3节)。


C99 出现的时候,大多数 CPU 都对除法的结果向零取整,所以这也被写入这一标准作为唯一允许的结果。


问:如果C语言有左值,那它也有右值吗?(p.41)


答:是的,当然。左值是可以出现在赋值 左侧 的表达式,而右值则是可以出现在赋值 右侧 的表达式。因此,右值可以是变量、常量或更加复杂的表达式。本书和C 标准一样,采用“表达式”这一术语来代替“右值”。(左值->空间 右值->值)


*问:前面提到:如果v有副作用,那么v += e 不等价于 v = v + e。可以解释一下吗?(p.41)


答: 计算v += e只会求一次v的值,而计算v = v + e则会求两次v的值 。在后一种情况下,对 v 求值可能引起的任何副作用也都会出现两次。在下面的例子中,i 只自增一次:

a[i++] += 2;

如果用 = 代替 += ,语句变成:

a[i++] = a[i++] + 2;

*

i 的值在别处被修改和使用了,因此上述语句的结果是未定义的。 i 的值可能会自增两次,但我们无法确定到底会发生什么。



问: C 语言为什么提供 ++ 和 -- 运算符?它们是比其他的自增、自减方法执行得快,还是仅仅更便捷? (p.42 )

对于现代编译器而言,使用 ++ 和 -- 不会使编译后的程序变得更短小或更快,继续普及这些运算符主要是由于它们的简洁和便利。



问:++--是否可以处理float型变量?

答:可以。自增和自减运算也可以用于浮点数,但实际应用中极少采用自增和自减运算符处理float型变量。


*问:在使用后缀形式的++或--时,何时执行自增或自减操作?(p.42)


答:这是一个非常好的问题,也是一个非常难回答的问题。 C语言标准引入了“顺序点”的概念,并且指出“应该在前一个顺序点和下一个顺序点之间对存储的操作数的值进行更新”。在C语言中有多种不同类型的顺序点,表达式语句的末尾是其中一种。在表达式语句的末尾,该语句中的所有自增和自减操作都必须执行完毕,否则不能执行下一条语句。

在后面章节中会遇到的一些运算符(逻辑与 、逻辑 或 、条件和逗号)对顺序点也有影响。函数调用也是如此:在函数调用执行之前,所有的实际参数必须全部计算出来。如果实际参数恰巧是含有++ 或 -- 运算符的表达式,那么必须在调用前进行自增或自减操作。



问:丢掉表达式语句的值意味着什么?(p.45)


答:根据定义,一个表达式表示一个值。例如,如果 i 的值为 5 ,那么计算 i + 1 产生的值为 6 。在末尾添加分号,把i+1 变成语句:

i + 1;

执行这条语句时,我们计算出了i + 1的值;但是我们没有保存此值(也没有以某种方式使用这个值),因此这个值就丢失了。



问:但是类似i = 1;这样的语句会如何呢?我没发现有什么东西被丢掉了。


答:不要忘记在 C 语言中 = 是一种运算符,它可以像其他任何运算符一样产生值。赋值语句

i = 1;

把1赋值给i。整个表达式的值是1,这个值被丢掉了。编写语句的首要目的是改变i的值,因此丢掉表达式的值不算什么大的损失。



最后的最后,创作不易,希望读者三连支持💖

赠人玫瑰,手有余香💖

相关文章
|
1月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
66 16
|
1月前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
77 18
|
1月前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
57 18
|
1月前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
52 13
|
1月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
37 3
|
1月前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
20 2
|
1月前
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
52 1
|
C语言
《C语言程序设计》一 第 1 章 程序设计概述
本节书摘来自华章出版社《C语言程序设计》一 书中的第1章,第1.1节,作者:赵宏 陈旭东 马迪芳,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1186 0
|
C语言
《C语言程序设计与实践(第2版)》——第1章 C语言与程序设计概述 1.1初见C语言程序
我国古代数学家张邱建在其编写的《算经》里提出了历史上著名的“百钱买百鸡”问题:今有鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。凡百钱买鸡百只,问鸡翁、母、雏各几何?对于这个问题,很多读者在小学或初中的竞赛中可能都见到过,而且通常都采用不定方程求解。
1156 0
|
1月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
63 23

热门文章

最新文章