C语言中的副作用、序列点、完整表达式

C语言中有个术语叫:副作用

副作用其实是对数据对象或文件的修改。(数据对象的定义是:用于存储值的数据存储区域)

例如语句 states = 50;

从C语言的角度来讲:这个赋值表达式的副作用是将变量的值设置为50;目的是对表达式求值;

但是使用赋值表达式的主要目的(真正目的)就是使用其副作用(将变量的值设置为50);

除此之外,递增、递减运算符也有副作用;我们使用它们其实主要目的是使用其副作用。即递增、递减的副作用;

例如printf()函数,我们使用它的目的是使用其副作用,其副作用是显示信息。它从C语言角度来说,目的是返回待显示字符的个数。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

序列点:

是程序执行的点,所有的副作用都在进入下一步之前发生;

语句中的分号标记了序列点;

当然不一定要分号才表示序列点;

完整表达式的结束也是一个序列点

例如:

while (guests++<10)

  printf("%d \n",guests)

上面程序当中:guests++<10 就是一个完整的表达式,该表达式的结束也是一个序列点。

guests++<10的意思是guests先跟10比较(比较会得到布尔值True、False,这个过程是求值,也就是C语言角度来说的目的),再递增(把guests的值加1,即对数据对象或文件的修改,即副作用。这个副作用其实也是我们编写程序角度的主要目的。)。

guests简单概括就是先比较(求值)再递增。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

完整表达式:

这个表达式不是另一个表达式的子表达式;

表达式语句中的表达式,循环条件的测试条件表达式,都是完整表达式。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

补充一下表达式expression、语句statement的概念:

表达式:

表达式是由运算符和运算对象组成的。
运算对象是运算符操作的对象。
对简单的表达式是一个单独的运算对象。
表达式最重要的特性之一就是每个表达式都有一个值。
要获得这个值,必须根据运算优先级规定的顺序去操作。

语句

语句是C语言的基本构建块。
一条语句相当于一条完整的计算机指令。
在C中,大部分语句都以分号结尾。
最简单的语句是空语句
真正有效的语句是可以改变值或调用函数;

注意:语句和表达式不能划等号;
语句的分类:表达式语句、迭代语句、跳转语句、声明等。

声明创建了名称和类型,并为其分配内存空间和位置;

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/grooovvve/p/9826127.html

时间: 2024-10-11 11:46:15

C语言中的副作用、序列点、完整表达式的相关文章

c语言中的副作用!!千万小心!

今天刚看完书上的副作用,博主觉得呢,副作用其实就在改变变量的值,也就是一个赋值操作!不过刚刚在知道上还是犯了错!!尴尬啊!! 大家都知道,c语言中的赋值操作符是自右向左结合的!! 下面有一个关于赋值中的副作用的例子: #include <stdio.h> int main() { int a = 3; a += a -= a*a; printf("%d\n",a); return 0; } 想到答案了吗?有没有人觉得答案是-3的呢? 小伙伴犯了和博主一样的错咯,正解应该是这

简述C语言中宏的作用及其副作用

引问:写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个? 答案:#define  MIN(A,B)  ( (A) <= (B)? (A) : (B) ) 知识梳理: 1). 标识#define在宏中应用的基本知识.直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法, 对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法. 2). 三重条件操作符的知识.这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更

C语言中的序列点

序列点是程序执行序列中一些特殊的点. 当有序列点存在时,序列点前面的表达式必须求值完毕,并且副作用也已经发生, 才会计算序列点后面的表达式和其副作用. 什么是副作用?举例子来说明. int a = 5; int b = a ++; 在给b赋值的语句中,表达式a++就有副作用,它返回a当前的值5后,要对a进行加1的操作. 哪些符号会生成序列点呢? ","会生成序列点. ","用于把多条语句拼接成一条语句. 例如: int b = 5; ++ b; 可由",&

C语言中标识符声明的几个关键字总结

C语言中声明一个名称就是把一个标识符与某个C语言对象相关联,如变量.函数或类型,C语言中可以声明的名称包括:变量.函数.类型.类型标志.结构成员与联合成员.枚举常量.语句标号和预处理器宏.除了语句标号和预处理器宏之外,所有标识符都在C语言声明中声明,变量.函数.类型放在声明的声明符中,类型标志.结构成员与联合成员和枚举常量在声明的某种类型说明符中声明,语句标号在C语言函数中出现时声明,而预处理器宏用#define预处理器命令声明. 如下列声明: extern const volatile uns

C语言中变量的存储类型

在C语言中,对变量的存储类型说明有以下四种: auto 自动变量register   寄存器变量extern 外部变量static   静态变量 自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式. 在介绍了变量的存储类型之后,可以知道对一个变量的说明不仅应说明其数据类型,还应说明其存储类型. 因此变量说明的完整形式应为:存储类型说明符数据类型说明符变量名,变量名-:例如: static int a,b;      说明a,b为静态类型变量 auto char c1,c2;

Java语言中反射动态代理接口的解释与演示

Java语言中反射动态代理接口的解释与演示 Java在JDK1.3的时候引入了动态代理机制.可以运用在框架编程与平台编程时候捕获事件.审核数据.日志等功能实现,首先看一下设计模式的UML图解: 当你调用一个接口API时候,实际实现类继承该接口,调用时候经过proxy实现. 在Java中动态代理实现的两个关键接口类与class类分别如下: java.lang.reflect.Proxy java.lang.reflect.InvocationHandler 我们下面就通过InvocationHan

C语言中随机数相关问题

用C语言产生随机数重要用到rand函数.srand函数.及宏RAND_MAX(32767),它们均在stdlib.h中进行了声明. int rand(void);//生成一个随机数 voidsrand(unsigned int seed); //为rand设置"种子"的值 srand()就是给rand()提供种子seed,如果srand每次输入的数值是一样的,那么每次运行产生的随机数也是一样的.通常的做法是以这样一句代码: srand((unsigned)time(NULL)); 来取

C语言中的三字母词

C语言中的三字母词(trigraph) 在ANSI C标准中,定义了9个三字母词(trigraph),三字母词就是几个字符的序列,合起来表示另一个字符.三字母词使C语言环境可以在缺少一些必需字符的字符集(比如,一些非常老式的键盘上没有[]{}#\^~|)上实现.也许是由于这些字符集我们基本上用不到,所以在大多数C语言的书籍中,我们都看不到对三字母词的讲解.下图列出了9个三字母词以及它们所代表的的字符. 源代码中的"三字母词",在编译阶段会被替换为"对应的字符".对于

c语言中会遇到的面试题

预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)         #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL我在这想看到几件事情:1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的.3) 意识到这个表达式将使一个16位