博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《C语言解惑》一1.3 逻辑操作符和增量操作符
阅读量:6618 次
发布时间:2019-06-25

本文共 2650 字,大约阅读时间需要 8 分钟。

本节书摘来自异步社区《C语言解惑》一书中的第1章,第1.3节,作者 傅道坤,更多章节内容可以访问云栖社区“异步社区”公众号查看

谜题1.3 逻辑操作符和增量操作符

请问,下面这个程序的输出是什么?

define PRINT(int) printf("%d\n",int)main(){  int x, y, z;  x = 2; y = 1; z = 0;  x = x && y || z; PRINT(x);                 (1.3.1)  PRINT( x || ! y && z );                   (1.3.2)  x = y = 1;  z = x ++ - 1; PRINT(x); PRINT(z);             (1.3.3)  z += - x ++ + ++ y; PRINT(x); PRINT(z);          (1.3.4)  z = x / ++ x; PRINT(z);  (1.3.5)}

f6d1d7a191ae3d097483a4469d18a4c74f1ce651
输出:
1                             (1.3.1)1                             (1.3.2)2                             (1.3.3)03                             (1.3.4)0?                             (1.3.5)

b31cdf720c2d3724ef777e59f8228fd4b33678aa

解惑1.3 逻辑操作符和增量操作符

1.3.1

初始值:x = 2, y=1, z=0

x = x&&y || z  按照操作符的优先级和关联规则进行绑定。

x = (x&&y) || z

x = ((x&&y) || z)

(x = ((x&&y) || z))

(x = ((TRUE&&TRUE) || z))   逻辑操作符的求值顺序是从左到右。逻辑操作符的操作数如果是0,则解释为FALSE;如果是非零值,则解释为TRUE。

(x = (TRUE || z))   只有两个操作数都是TRUE,逻辑与(&&)的结果才会是TRUE;其他情况的求值结果都将是FALSE。

(x = (TRUE ||任意值))  只要有一个操作数是TRUE,那么不管另一个操作数是什么,逻辑或(||)的结果都将是TRUE。因此,我们不必再对这个表达式继续求值了。

(x = TRUE)

(x = 1)

1

再谈define:这个程序里的define语句与前一个程序里的define语句有所不同:这个程序里的“PRINT”是一个带参数的宏。在遇到带参数的宏时,C语言的预处理器将分两步进行替换:先把宏定义里的形式参数替换为实际参数,再把宏调用替换为宏定义体。

在这个程序里,“PRINT”宏有一个形式参数int。“PRINT(x)”是使用实际参数“x”进行的“PRINT”调用。在扩展“PRINT”调用的时候,C语言预处理器会先把宏定义里的所有“int”替换为“x”,再把宏调用“PRINT(x)”替换为结果字符串“printf``("%dn", x)”。请注意,形式参数int并不是匹配单词“printf”里的“int”字符的。这是因为宏定义里的形式参数是标识符——具体到这个例子,形式参数int只对标识符int进行匹配和替换。

1.3.2

初始值:x = 1, y=1, z=0

x || ! y&&z

x || (! y)&&z  对操作符和操作数进行绑定。

x || ((! y)&&z)

(x || ((! y)&&z))

(TRUE || ((! y)&&z))  按从左到右的顺序求值。

(TRUE ||任意值)

TRUE,即1

1.3.3

初始值:x = 1,y=1

z = x ++ - 1

z = (x ++) – 1  对操作符和操作数进行绑定。

z = ((x ++) - 1)

(z = ((x ++) - 1))

(z = (1 - 1)),此时x=2  出现在操作数右边的“++”操作符是所谓的“后”递增操作符:先在表达式里用该操作数完成有关的计算,再对它进行递增。

(z = 0)

0

1.3.4

初始值:x = 2, y=1, z=0

z += - x ++ + ++ y

z += - (x ++) + (++ y)   一元操作符的关联是从右到左,因而“++”操作符将先于一元操作符“-”得到绑定。(事实上,如果先去绑定“-”操作符的话,这个表达式将无法成立。这是因为“++”和“--”操作符都要求以一个变量(更准确地说,以一个“左值”[1])作为其操作数。“x”是一个左值,但“-x”不是。)

z += (- (x ++)) + (++ y)

z += ((- (x ++)) + (++ y))

(z += ((- (x ++)) + (++ y)))

(z += ((-2) + 2)),此时x=3, y=2

(z += 0)

(z = 0 + 0)

(z = 0)

0

按照从内到外的顺序依次求值。

关于记号:计算机程序的源代码文本是由一系列记号构成的,而编译一个程序的第一项工作就是把那些记号一个一个地分解开。这在绝大多数场合都没有什么困难,但有些字符序列可能会让人感到困惑。比如说,如果上面这个例子里的表达式有一部分根本没有空格——就像下面这样:

x+++++y

那么,这个没有空格的表达式与有空格的表达式还会是等价的吗?

为避免产生二义性,如果一个字符串能够解释为多个操作符,C语言编译器将按照“构成操作符的字符个数越多越好”的原则来作出选择。根据这一原则,“x+++++y”解释为:

x++ ++ + y

而这已经不是一个合法的表达式了。

1.3.5

初始值:x = 3,z=0

z = x / ++ x

z = x / (++ x)

z = (x / (++ x))

(z = (x / (++ x)))

如果你还像以前那样按照从内到外的顺序对这个表达式进行求值,即先对x进行递增,然后作为除数、用x作被除数去进行除法计算。问题是:作为被除数的x到底是几?是3还是4?换个问法,被除数到底是递增前的x值,还是递增后的x值?请注意,C语言并没有对这种“副作用”作出明确的规定,而是由C编译器的编写者决定的[2]。这个例子的教训是:如果你无法断定会不会产生副作用,那么就尽量不要写这样的表达式。

转载地址:http://snypo.baihongyu.com/

你可能感兴趣的文章
市场调研报告:企业级信息防泄漏大趋势
查看>>
济南企业短信平台的价格如何?
查看>>
requirejs
查看>>
php printf() 输出格式化的字符串
查看>>
VS2013下的64位与32位程序配置
查看>>
浅谈C中的指针和数组(二)
查看>>
SSM+Maven+IDEA增删改查
查看>>
微信小程序开发模板消息的时候 出现 errcode: 41028, errmsg: "invalid form id hint:
查看>>
2001年日语能力考试二级真题及答案
查看>>
移动端页面布局
查看>>
FUNCS.H中的函数声明
查看>>
让织梦CMS的后台编辑器支持优酷视频
查看>>
Python语言中round函数的一个疑惑
查看>>
Spring事务隔离级别,事务传播行为
查看>>
CRC是什么?
查看>>
每次看完羽毛球赛
查看>>
第一章练习题
查看>>
三、JVM垃圾回收1(如何寻找垃圾?)
查看>>
RabbitMQ-从基础到实战(2)— 防止消息丢失
查看>>
【译】ExtJS 4.1会带来什么
查看>>