当前位置: 首页 > news >正文

C语言中的副作用、序列点以及复杂表达式的求值顺序

C语言中复杂表达式的求值顺序

num = (5 + 2) * (9 * 6);

如果我问你:上面的c程序在执行的时候到底是先算(5 + 2)还是(9 * 6)?你会怎么回答?

无非就两种:先算(5 + 2)或者先算(9 * 6)对吧?那么我来告诉你,这两种结果都不对,答案是不确定,你应该先问编译器。

副作用和序列点

在解释上面的概念之前,我们先来介绍两个专业术语:副作用、序列点

副作用

副作用(side effect)是指对数据对象或文件的修改。
例如:

states = 50;

它的副作用是将变量的值设置为50。

看起来,副作用更像是主要目的,其实并不是。从C语言的角度来看,上面的代码的主要目的是对表达式求值。

给出4 + 6,C会对齐求值得到10,同理,给出states = 50;C语言会对其进行求值得到50。

在C语言的眼里,上面的程序更像是这样的:

(states = 50);

类似的,printf函数显示的信息其实是它的副作用(printf的返回值是待显示字符的个数,也就是放入输出缓冲区字符的个数),不懂缓冲区的可以看我的这篇文章:你真的理解printf函数吗?

序列点

序列点(sequence point)是程序执行的点,在这个点上,所有的副作用都会在进入下一步之前发生。语句中的分号标记了一个序列点。

分号的意思是:在这个语句之前,赋值运算符、递增运算符和递减运算符对运算对象做的改变必须在程序执行下一条语句之前完成。

求值顺序

C把先计算哪一个部分的决定权留给编译器的设计者,以便针对特定系统优化设计。
也就是说,对于开始的那个程序,哪一段表达式先被计算是不确定的。

但是,对于逻辑运算是个例外。

在C语言中,保证逻辑表达式的求值顺序是从左往右。&&和||都是序列点,所以一个程序在从一个运算对象执行到下一个运算对象之前,所有的副作用都会生效。

并且,重要的一点是,C一旦发现某个元素让表达式无效,便立即停止求值。

有了上面的规则,才能写出下面的代码:

while ((c = getchar()) != ' ' && c != '\n');

在上面的代码中,读取字符直到遇到第一个空格或者换行符停止,需要注意的是,如果没有上面的规则,c != '\n'这个语句就有可能在c = getchar()之前执行了,这样一来,就不能保证语义的正确性了。

http://www.lryc.cn/news/278900.html

相关文章:

  • C++学习笔记——队列模拟
  • jvm垃圾回收相关的算法
  • 每日coding
  • 软件工程_复习
  • 07GoF之三种工厂模式
  • JAVA面试部分——后端-线程前篇
  • 【小沐学C++】C++ 实现鼠标键盘钩子HOOK
  • 【pycharm】常见问题与解决
  • flask web学习之表单(一)
  • @ControllerAdvice 使用场景
  • 二极管选型怎么选?常用参数要熟练~
  • 【小白专用】C#关于角色权限系统
  • 代码随想录算法训练营
  • 统计学-R语言-3
  • spring动态控制定时任务
  • 3. Mybatis 中SQL 执行原理
  • 第一次在RUST官方论坛上留言发布我的Rust板箱
  • LabVIEW 智能化矿用定向钻机液压系统监测
  • GO数据库操作
  • PyTorch简单理解ChannelShuffle与数据并行技术解析
  • MySQL 8查询语句之查询所有字段、特定字段、去除重复字段、Where判断条件
  • LLaMA-Factory添加adalora
  • 多端多用户万能DIY商城系统源码:自营+多商户入驻商城系统 独立部署 带完整的安装代码包以及搭建教程
  • Qt 6之七:学习资源
  • 解决大模型的幻觉问题:一种全新的视角
  • mysql进阶-重构表
  • Element-ui图片懒加载
  • Linux系统——DNS解析详解
  • 初识Ubuntu
  • Casper Network (CSPR)2024 年愿景:通过投资促进增长