您好,欢迎进入u8国际电动伸缩门有限公司官网!
u8国际|u8国际官方网站|u8国际网址最新

联系我们

邮箱:youweb@admin.com
电话:@HASHKFK
地址:广东省广州市番禺经济开发区 在线咨询

u8国际常见问题

u8国际-u8国际官方网站-网址最新C语言中自增自减表达式的未定义行为doc

发布日期:2025-01-15 14:05 浏览次数:

  u8国际,u8国际官方网站,u8国际网站最新,u8国际网站,u8国际网址,u8国际链接

u8国际-u8国际官方网站-u8国际网址最新C语言中自增自减表达式的未定义行为doc

  C语言中自增自减表达式的未定义行为 摘要:自增自减运算符是C语言的一个特色,本文通过表达式中对 一个变量进行多次自增或自减运算时产生的未定义行为进行了详细介绍, 望帮助大家正确使用自增自减运算符。 关键词:C;自增自减运算符;未定义行为 中图分类号:TP312文献标识码:A文章编号:1674-7712(2014) 02-0000-01 一、自增自减运算符 C语言提供了两个用于算术运算的单目运算符:自增(++)和自减(--)。 有两种用法:前置运算(先增减后运算),后置运算(先运算后增减)。下 类代码段: 在不同的编译器上运行会有不同的结果: 一种是:21,8,一种是:22,8,一种是24,8; 很奇怪吧,一样的表达式不同的编译器,运行结果会不同,虽然可以 通过Debug反汇编分析出不同,那为什么会这样?哪个是正确答案?遗憾 的是这样的题目是并没有答案,如果真的要给一个答案,可以是未定义行 为。 二、C语言中未定义行为(Undefinedbehavior) 未定义行为是一个非常微妙的话题,在C中许多貌似合理的行为实际 上都有着不确定的行为,并且这通常是程序中BUG的源头。未定义行为, 就是C标准没有对其进行定义,程序员不能预测会发生什么事的计算机代 码,编译器可以随意进行计算,简单说就是语言规格在定义时为了编译器 工作的弹性和效率,会刻意不去规定某些规格,如果我们的程序依赖这些 没有规定的特性时,就称之为未定义行为,这样的程序语句在不同的编译 器上编译会得到不同的结果。另外由“实现”定义的行为,这里的实现指 的是C的不同编译器,也是未定义行为。 C中的自增自减运算就属于未定义行为,因为C没有规定i++或者++i 的加1动作到底发生在一个语句的那个时刻(序列点)执行,所以不同编 译器在不同的序列点上执行加1动作就可能有不同的结果。尽管后缀前缀 自增自减操作符++和--分别在输出其旧值之后和输出新值之前执行加1减 1运算,但这里的“之后”常常被误解。因为没有任何保证确保后置前置 自增自减会在输出变量原值之后以及输出新值之后会对表达式的其它部 分进行计算之前以及之后立即进行,也不能保证变量的更新会在表达式完 成之前的某个时刻进行,这样就导致结果的不同。这样导致未定义行为会 包含多个不确定的副作用,上述表达式是有副作用的,因为在序列点之间, 变量的值不能保证行为唯一性,也就是说第一次执行完++i,它在内存中 的值可能改变也可能不变。 三、未定义行为的副作用 不确定副作用是指在同一个表达式中使用导致同一对象修改两次或 修改以后又被引用的自增,自减和赋值操作符的任何组合。C语言允许在 一个表达式中使用一个以上的赋值类运算,包括赋值运算符、自增运算符、 自减运算符等。这种灵活性使程序简洁,但同时也会引起副作用。副作用 主要表现在:使程序费解,并易于发生误解或错误。除此之外,C中的任 何的未定义行为都有可能(无论是编译期还是运行期)产生一些格式化你 的硬盘的、做一些你完全想象不到的事情的代码,所以不要试图探究这些 东西在你的编译器中是如何实现的(这与我们C教科书上的许多练习正好 相反)。另外C/C++规定,任何依赖于特定计算顺序、依赖于在顺序点之间 实现修改效果的表达式,其结果都没有保证,因此如果在任何完整表达式 里存在对同一变量的多次引用,那么表达式里就不应该出现对这一变量的 副作用,否则就不能保证得到预期结果,还有这不是在某个系统里试一试 的问题,因为我们不可能试验所有可能的表达式组合形式以及所有可能的 上下文。但这类表达式在教材中很多,难道只是未定义行为的副作用,再 来研究一下这类表达式的合法性。 四、表达式的合法性 计算机科学家BrianW.Kernighan主编的《TheCProgramming Language》明确指出:自增与自减运算符只能作用于变量,不能应用于表 达式以及整数,例如++(a+b)与10++,constintN=0;N++;都是非法 的。 为什么?因为这些表达式实际上包括了一个赋值运算,a++等价于 a=a+1;C语言中赋值运算符存在左值,只能变量可以作为左值,表达式以 及整数不能作为左值,因为它们没有确定的内存地址。因此++(a+b)等 价于(a+b)=(a+b)+1是不允许的,以此分析,(a++)+(a++)这个表 达式中的后一项是非法的,表面上它只是一个a++,但是在第一个a++的 作用下,a已经变成a=a+1;因此第二个的a++则成为(a+1)++了,这是 非法的。一般地,在一个表达式中,对同一个变量进行多次自增或自减运 算都是非法的。C语言之父DennisM.Ritchie还提醒,编译器应在这种情 况下会给出警告,事实上Linux平台下的编译器GCC确实会对此给出警告 (VC++6.0没有):Warning:operationon‘a’maybeundefined; C++Primer解释:使用了未定义行为的程序都是错误的,即使程序能 运行也只是巧合,未定义行为源于编译器不能检测到的错误或太麻烦以至 无法检测的错误。然而,含有未定义行为的程序在某些编译器中可以正确 执行,但并不能保证同一程序在不同编译器中甚至在当前编译器的后继版 本中会继续正确运行,也不能保证程序在一组输入上正确运行并在另一组 输入上也正确运行。总而言之,绝对不要写这种表达式,否则或早或晚会 在某种环境中遇到麻烦。因此书写程序时,要尽可能的保持清晰易懂,代 码除了供人阅读以外,简单清晰的程序也不容易出错。 五、未定义行为的使用 既然C、C++、底层虚拟机(LLVM)IR中都有未定义行为,那么肯定 有意义,现代计算机是以二进制逻辑运算为基础,“对于确定的输入,其 输出是确定的”,行为必然是确定的。但是,如果不为计算机的基础计算 模型引入不确定性,人工智能(AI)不可能真正实现。另外为了使C应用 程序获得更好的性能,可以通过优化编译器产生高性能,而未定义行为使 优化成为可能。 六、结束语 在教科书以及等级考试中,对一个变量在表达式中多次自增自减很常 见,本文针对表达式运行结果不同的疑惑进行了解答,详细介绍了表达式 中涉及到的未定义行为,希望对大家有正确的指导意义。 参考文献: [1]谭浩强.C语言程序设计[M].北京:清华大学出版社,2011. [2]黄玉兰.有关C语言输出函数中的自增自减运算符在不同编译环境 中的探讨[J].科技致富向导,2013(20).

联系方式

全国服务热线

@HASHKFK

手 机:@HASHKFK

地 址:广东省广州市番禺经济开发区

扫一扫,加微信

Copyright © 2002-2024 u8国际电动伸缩门有限公司 版权所有 非商用版本 备案号: