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

联系我们

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

u8国际常见问题

对C语言中“无定义”代码的剖析u8国际-u8国际官方网站-网址最新

发布日期:2024-12-08 09:31 浏览次数:

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

对C语言中“无定义”代码的剖析u8国际-u8国际官方网站-u8国际网址最新

  第6卷第4期2006年12月温州职业技术学院学报JournalofWenzhouVocational&TechnicalColJelse、b1.6NO.4Dec.20o6对C语言中“无定义”代码的剖析夏跃伟,孙爱民(漯河职业技术学院计算机系,河南漯河462002)[摘要]在c语言中,具有“副作用”的“无定义”代码会带来难以预料的后果,是编程人员必须避免的。但在许多c语言教材中,却存在把“无定义”代码当作正确例题讲解的问题,容易使学习者陷入c语言学习的“陷阱”。本文从实例入手,分析c语言中“无定义”代码存在的问题,并就如何避免该问题提出解决方法。【关键词】c语言;“无定叉”代码;序列点;副作用【中图分类号】TP3ii.i【文献标识码】A[文章编号】I67卜4326(2006)04—0039~03AnAnalysisof¨Undefined¨CodeinProgrammingLanguageCⅪAYuewei.SUNAinfinlComputerScienceDepartment,LuoheVocationalandTechnicalCollege.Luohe.462oo2.China)Abstract:InProgrammingLanguageC.the’’Undefined”Codewith”sideefects”willbringsomeunpredict—ableresults,andprogrammersmustavoidthem.ButinsometextbooksofProgrammingLanguageC,the”Unde—fined”Codeisdemonstratedasacorrectexample,whichwillmisleadstudentsofProgrammingLanguageC.Basedonexamples,thispapermakesananalysison”Undefined”Code,andgivessomesolutionstotheproblem.Keywords:ProgrammingLanguageC:”Undefined”Code;SequencePoint;Sideeffects0引言C语占是目前最优秀的程序设计语言之一,包含丰富的运算符和数据类型,具有操作灵活、运行效率高、可移植性强等特点,被广泛应用于系统软件和应用软件的开发。在高校的计算机专业与相关专业中,c语占已成为r程序设计的核心课程但笔者发现,在许多C沿占教材中却仃征把“无定义”代码当作确例题讲解的问题。这一现象容易使学习者陷入C语言学习的“陷阱”,对学生能否正确理解C语言知识点、培养良好的编程风格都有着直接关系。本文从实例人手,分析C语占中“无定义”代码存在的问题,井就。如何避免该问题提出解决方法。1C语言中“无定义”代码问题的提出‘【例1】求n的值。;fI}include”stdi0.h”intmain(){intn,m=3:n=(++m)+(++m)+(++m):printf(”n=%d\n”,n);returnO:}上例中,类似“n=(十十m)十(十十m)+(十十m);”的语句是一些教材中经常出现的,那么n的值足多少?TUrbOC和C++Builder中n=l8,但枉Vc的Debug模式和IGNU的GCC模式下却是n=16,更奇怪的是,在VC的Debug模式下n=l6,但在Release模式下又成rn=l8,到底是怎么回事?不同的编译器会出现不Il—J的结果,町相同的编译器对同一段程序怎么也会有两种结粜?为寻找原因,分别在VC的Debug模式和C++Builder对以上程序进行了反汇编。在VCDebug模式下的汇编代码,如图l所示;杠C十+bui1der下的汇编代码,如l垒I2所示。其解释分析如下:[收稿日期]2006一IO-08[作者简介]夏跃伟(1972-)..河南临颍人,ijI}河职业技术学院计算机茉讲师;孙爱民(1974一),男。河南许昌人,漯河职蛾技术学院计算机系讲师,硕士维普资讯州职业技术学院学报2006年l2月豳2C++Bu11der下的汇编代码我们从圈l、图2可以看出,VCDebug模式下生成的指令悬严格按照表达式生成的,而c++Bui1der则对指令进行了优化,导致同样的程序经过不同的编译器编译后,形成了有“差异”的结果。为什么会发生这种“差异”呢?那么标准答案是什么呢?这样的情况该怎样处理呢?2闻题的分析殛解决C语言是一种基于表达式的语言,即C语言语句中最基本的构成原子是表达式。一个表达式的执行会造成两种结果:计算的结果;对环境的修改(也就是对变量值的修改)。如果一个表达式造成了第二种结果,我们就说这个表达式具有“副作用”,当不确定的“副作用体现出来时,就会造成“差异”。为避免“副作用”造成的“差异”,我们要了解“序列点”(sequencepoints)的概念。C99对它的定义是Atcerrainspecifiedpointsintheexecutionsequeneecalledsequencepoints”,通俗地说,就是指程序运行中的一个特殊时19点,在这个点之前的所有‘‘副作用会结束,并且后续的“副作用”还没发生。在c语言中,任何完整表达式运算结束的那个0040102F到00401035完成了一个 ++m的运算, 此 时的 m=4: 00401038 到 0040103E完成了一个 ++m的运算,此 时的 m=5; 00401041到 00401044 将 edx=m+m即 edx=lO,丽 m 的值未改变: 。 00401047 到 0040l 04A将 eax=m+l 即 eax=6,而 m 的值没有 改变 : 0040104D到 00401050 将 edx=edx+eax,即edx=16,m 的值未改变; 0040l 053 将 edx 的值赋给了n, 最 终 ,n=l 6 。 0040l l75 到 00401 l7B是完全一样的指令,都悬使 ‘ m=m+l ,共加了 3 次,即 m=6; .。 00401 17E到 00401 184是把 eax= ,即eax=l 8; 0040l l 87 是把 eax 赋值给了 n, 最终,n l8。 时间点是序列点、语句的结束标志——分号 “;”也蹙 序列点,因此,C 语句中由赋值、自增或 自减等操作 。 引起 的 “副作用”在分 号之前必 须结束。 C 9 9 规定,如果一个单独的对象在相邻的序列点 - 之间被修改了两次或两次以上的话,那么结果是_束定 。 义的。I例 l 】中,“i nt n,m=3 ;”中的 “;”是一个序列 点,“n= (++m)+ (++m) + (++m) ;”是个完整表达式,这个 表达式运 算 结束 的那 一点也 是一个 序 列点, 也就 是 、 说,“(++m)+ (++m)+(++m) ”位于两个序列点之间。【例 l 】中,m的值在两个序列点之间被修改了三次,按髑 c 标准的规定,这 然是错误的! 【例 l 】中的代码I曩;际 上 是一段 “无 定义 ”的代码 ,这会 引起 “多个不确定 的副作用”( “多个不确定副作用”是指在同一个表达式 中使 用导致 同一对 象修改两次或修 改以后又被 引用的 自增 、自减和赋值操作符的任何组合) 。 此外 ,基 于表达 式的语 言还有 一个很 大的问麒就 是表达式的计算顺序,在 C 9 9 标准中既没有规定大部 分的一元、二元 ( 除了 “,”“&& “l l”) 的运算符的 结合顺序,也没有规 定函数调用 的计算顺序,决定运 算顺序 的唯一依据就是优先级 。当进行操作符的计算 维普资讯 第 6 卷第 4 期 夏跃伟 ,孙 爱民:埘 c 晤富中 “无定义 ”代码 的剖析 4 l 时,如果遇到序列点,则序 列点处的值必须被优先计 算,以保证一些特殊用途,然后才恢复正常的计算。但 在编 译器中,语句在执行 时计算顺序并不确定 ,由于 许多编译器添加 了优化措施 ,因而在编译器进入到优 化阶段时会 改变表达式的顺 序, 以求生成最 高效率的 代码。所 以, 坤p编译器 呵能是这样编译, 而另一种 编译器可能 又是那样编译 ,甚至有时一个编译 器可能 在不同模式 下使用不 同的顺 序,最终就会得 出不 同的 结果 。 正是基f 以上两方面的原因,【例 l 】中,m的值是 在没 有时间序列点保 鹾的情 况下被更新 的,值的正确 性无法保 证,而这段代码本 来就 是 “无定义” 的 ( 连 续对 m改变和取值,而中间又没有 “序列点”),所 以, 无论编译器怎样处理都是正确的。因此,【例 l 】中的正 确结 果是—— 不知道, 因为这 样的代码本身就 足错误 的,是不 该写 出来的 。 以下再例举一个 例子进 行分析。 【例2】#i nclude

  main( ) { i nt i = l 0 : i = i一一 一一一i· ( i = 一 3 ) · i++ + ++i ; print f ( ”i = %d\n”,i ) : ) 结 果 一 l 2 8 - 8 6 - 8 5 - 6 3 4 2 l 3 6 4 2 编译器 Tandy 60 0 0 Xeni x 3 .2 l BM Power PC AI X 3 .2 .5 Sun Sparc acc ( K&C编译器 ) GCC,HP UX 9 .0 。 Powe rC.2 .0 Mi c r osof t C++ 7 .0 Turbo c/c抖 3.0,Turbo c/c* 4.5 Dec VAX/VMS Mi Cr osof t 5 .1 从上例中可以看出,经过不同的编译器编译,i 的 值也 是不同的。尽 管每种 编译器 都会产生确定的值 , 但到底哪个 是正确 的,却没 有标 准答案。这利·令人意 想不到的结果,是 由于表达式本身 的缺 陷引起的 ,因 为它 包含 了许 多具 有 “副作用 ”的操作符,它的求值 顺序存在歧义 。当然,这些结果 中,也 叮能有我 们期 望的结果,但这并不能说明程序是. I 确的。事实 ,如 果类似这样 的无定 义代码应用到实 际工作 中,或许 会 造成更严重 的后果 ,甚 让程序崩 溃。因此,程序 员 应 该绝对避免 “无 定义” 代码 的出现。 经过 以上分析 ,我 们知道 r 有 关序列点和求值 顺 序问题。C 语古中,序列点通常出现枉以 几个 断: 函数调用的参数计算之后;“&&、l l 、? 、:”等运算符的 第 一个运 算之 后 ;变 量初 始 化之 后 和完 整表达 式之

联系方式

全国服务热线

@HASHKFK

手 机:@HASHKFK

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

扫一扫,加微信

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