【C语言学习笔记】《C程序设计语言》 第2章(类型、运算符与表达式)——第2节(类型转换、运算符、表达式)

Warning:
为了避免非零基础人群感到身体不适、头晕恶心、易怒及粗口,请不要查看以下内容。

上一节我们学习了变量、常量、数据类型、声明。本节我们继续学习类型、运算符、表达式的相关知识。运算符包括:算术运算符、关系运算符、逻辑运算符、自增运算符、自减运算符、按位运算符、赋值运算符等

第2章 类型、运算符与表达式

2.5 算术运算符

二元算术运算符包括:+ - * / %(取模运算符)。整数除法会截断结果中的小数部分。表达式 x % y 的结果是x除以y的余数,当x能被y整除时,其值为0。

取模运算符不能用于float和double类型。在有负操作数的情况下,整数除法截取的方向以及取模运算结果的符号取决于具体机器的实现,这和处理上溢和下溢的情况是一样的。

二元运算符+和-具有相同的优先级,它们的优先级比算术运算符 * / % 低,而运算符 * / %的优先级又比一元运算符+和-的优先级低。算术运算符采用从左到右的结合规则。

本文末尾会单独开贴讨论 取模与取余运算的异同 以及 与《孙子问题(中国剩余定理)》和凯撒密码的关系

2.6 关系运算符与逻辑运算符

关系运算符包含下列几个运算符: > >= < <=
它们具有相同的优先级。相等性运算符的优先级仅次于它们:== !=
关系运算符的优先级比算术运算符低。因此 i < lim - 1 等价于 i < (lim - 1)

逻辑运算符&&与||有一些较为特殊的属性。由&&和||连接的表达式按从左到右的顺序进行求值。并且,在知道结果值为真或假后立即停止运算。绝大多数C语言程序运用了这些属性。

运算符&&的优先级比||的优先级高,但两者都比关系运算符和相等性运算符的优先级低。

逻辑非运算符 ! 的作用是将非0操作数转换为0,将操作数0转换为1.

2.7 类型转换

当一个运算符的几个操作数类型都不同时,就需要通过一些规则把它们转换为某种共同的类型。一般来说,自带转换是指把 “比较窄的” 操作数转换为 “比较宽的” 操作数,并且不丢失信息的转换。例如:在计算f + i时,将整型变量i的值自动转换为浮点型。不允许使用无意义的表达式,例如:不允许float类型的表达式作为数组下标。针对可能导致信息丢失的表达式,编译器可能会给出警告,比如把较长的整数型赋值给较短的整数型变量,把浮点型值赋值给整型变量,但这些表达式并不非法。

由于char类型就是较小的整型,因此在算术表达式中可以自由使用char类型的变量,这就为实现某些字符转换提供了很大的灵活性。

将字符类型转换为整型时,我们需要注意一点。C语言没有指定char类型的变量是无符号变量还说带符号变量。当把一个char类型的值转换为int类型的值时,其结果有没有可能为负整数?对于不同的机器,其结果也不同,这反映了不同机器结构之间的区别。在某些机器中,如果char类型值的最左一位为1,则转换为负整数(进行“符号拓展”)。而在另一些机器中,把char类型转换为int类型时,在char类型值的左边添加0,这样导致结果总是正值。

C语言的定义保证了机器的标准打印字符集不会是负值,因此,在表达式中这些字符总是正值。但是,存储在字符变量中的位模式在某些机器中可能是负值,而在另一些机器上是正值,为了保持可移植性,如果要在char类型的变量中存储非字符数据,最好指定signed或unsigned限定符。

C语言中,很多情况下会进行隐式的算术类型转换。一般来说,如果二元运算符的两个操作数具有不同的类型,那么在进行运算之前先要把“较低”的类型提升为“较高”的类型。运算的结果是较高的类型。但是,如果没有unsigned类型的操作数,则只要使用下面这些非正式规则:

1.如果其中一个操作数类型为long double,则将另外一个操作数转换为long double
2.如果其中一个操作数的类型为double,则将另一个操作数转换为double
3.将char与short类型的操作数转换为int
4.如果其中一个操作数为long,则将另一个操作数的类型也转换为long

注意,表达式中的float类型的操作数不会自动转换为double类型,这一点与最初的定义有所不同。一般来说,数学函数使用双精度浮点型的变量。使用float类型主要是为了在使用较大的数组时节省存储空间,有时也为了节省机器执行时间。

当表达式中出现unsigned类型时,转换规则要复杂一些。主要原因在于,带符号值与无符号值之间的比较运算是机器相关的,因为它们取决于机器中不同整数类型的大小。例如,假定int类型占16位,long类型占32位,那么,-1L>1UL,这是因为-1L将被提升为unsigned long类型,因而成为一个比较大的正数。

赋值时也要进行类型转换。赋值运算符右边的值需要转换为左边变量的类型,左边变量的类型即赋值表达式结果的类型。

前面提到过,无论是否进行符号拓展,字符型变量都将被转换为整型变量。当把较长的整数转换为较短的整数或char类型时,超出的高位部分将被丢弃。

由于函数调用的参数是表达式,所以在把参数传递给函数时也可能进行类型转换。在没有函数原型的情况下,char与short类型都将被转换为int类型,float类型都将被转换为double类型。因此,即使调用函数的参数为char或float类型,我们一般也把函数参数声明为int或double类型。

最后,在任何表达式中都可以使用一个称为 强制类型转换 的一元运算符强制进行类型转换。在下列语句中,表达式将按上述转换规则被转换为类型名的类型。

(类型名)表达式

2.8 自增运算符与自减运算符

C语言提供了两个用于变量递增与递减的特殊运算符。自增运算符++使其操作数递增1,自减运算符–使其操作数递减1。

++与–的特殊地方就在于它们既可以做前缀运算符也可以做后缀运算符。它们都可以将变量递增或递减1,但是它们有一点不同。表达式++n先将n的值递增1,再使用n的值。而表达式n++先使用n的值在将n递增1。简单的说,区别就在于执行顺序不同。这点比较简单,不详细讲解,实战中会使用到。

2.9 按位运算符

C语言提供了6个位操作运算符。这些运算符只能作用于整型操作数,即只能作用于带符号或无符号的char、short、int与long类型:
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XOR)
<< 左移
>> 右移
~ 按位取反(一元运算符)

本块内容需了解二进制,这里暂时不讲解,以后再做补充。(可以先看我发的编码中进制转换相关知识)

2.10 赋值运算符与表达式

i = i + 2 等价于 i += 2 ,其中 += 为赋值运算符,其它大多数二元运算符也有这种用法。

2.11 条件表达式

下面这组语句:

if (a > b)
      z = a;
else
      z = b;

用于求a与b中的最大值,并将结果保存到z中。条件表达式(使用三元运算符 “?:”) 提供了另外一种方法编写这段程序及类似的代码段。在表达式
expr1 ? expr2 : expr3
中,首先计算expr1,如果其值不等于0(为真),则计算expr2的值,并以该值为条件表达式的值,否则计算expr3的值,并以该值为条件表达式的值。expr2与expr3中只能有1个表达式被计算。因此,以上改写为:

z = (a>b) ? a : b;      /* z = max(a, b) */

应该注意,条件表达式实际上就是一种表达式。它可以用在其它表达式可以使用的任何地方。如果expr2与expr3的类型不同,结果的类型将由本章前面讨论的转换规则制定。例如,如果f为float类型,n为int类型,那么表达式

(n > 0) ? f : n;

是float类型,与n是否为正值无关。

条件表达式中的第一个表达式两边的圆括号并不是必须的,这是因为运算符 ?: 的优先级非常低,仅高于赋值运算符。但我们还是建议使用圆括号,因为这可以使表达式的条件部分更易于阅读。

2.12 运算符优先级与求值次序

本章终于结束了,在结束前,我们看一下各种运算符的优先级与结合性。

下表总结了所有运算符的优先级与结合性,其中的一些规则我们还没有讲述。
同一行中的各运算符具有相同优先级,各行间从上往下优先级逐行降低。

运算符 结合性
() [] -> . 从左至右
! ~ ++ – + - * & (type) sizeof 从右至左
* / % 从左至右
+ - 从左至右
<< >> 从左至右
< <= > >= 从左至右
== != 从左至右
& 从左至右
^ 从左至右
| 从左至右
&& 从左至右
|| 从左至右
?: 从右至左
= += -= *= /= %= &= 从右至左
^= |= <<= >>= 从左至右
, 从左至右

注:一元运算符+、-&与*比二元运算符+、-、&与*的优先级高。
运算符()表示函数调用 运算符 -> 和 . 用于访问结构成员,第6章将讨论这两个运算符以及sizeof(对象长度)运算符,第5章将讨论运算符 * (通过指针间接访问) 与 & (对象地址),第3章将讨论逗号运算符。

在任何一种编程语言中,如果代码的执行结果与求值顺序相关,则都是不好的程序设计风格。很自然,有必要了解哪些问题需要避免,但是,如果不知道这些问题在各种机器上是如何解决的,就最好不要尝试运用某些特殊的实现方法。

总结

以上就是第二章的全部内容。我们分成了2个小节来学习。第一节我们学习了变量、常量、数据类型和声明,第二节我们学习了类型转换、运算符以及表达式。这些都是C语言的核心基础。今后的学习中要坚持写笔记,深刻理解,打牢基础。俗话说:“基础不牢,地动山摇”。

发布了14 篇原创文章 · 获赞 0 · 访问量 498

猜你喜欢

转载自blog.csdn.net/AtomTeam/article/details/104167803