论文部分内容阅读
【摘要】 C++程序良好的可移植性使得C++语言成为程序设计人员的首选工具语言,然而现实当中,由于各种因素的影响,导致很多程序员写出来的代码的可移植性较差。本文从C++标准、程序开发人员的习惯和专业书籍的规范化等多个角度出发,分析了这一问题产生的原因,并提出了相应的解决办法。
【关键词】 C++标准;可移植性;编译环境
【中图分类号】:G623.58【文献标识码】:B 【文章编号】:1009-9646(2008)05-0113-01
1983年第一个C++程序投入使用,1994年8月,ANSI/ISO委员会草案登记,这便是业内所称的早期的C++标准,1998年11月,ISO/IEC:98-14882标准(以下简称98标准)被批准,标志着C++代码的标准化正式诞生[1]。目前标准委员会正在修订C++标准,并拟于2009年发布修订后的09标准。可以预见,C++语言作为程序开发的主要工具仍将延续很长的一段时间。
C++语言诞生以来,延续了C语言的重要特征,即C++源程序良好的可移植性。正是这一特性,使得C/C++语言长期以来一直是程序开发人员的首选。然而,国内程序设计人员由于长期受到单一编译环境的影响,甚少关注C++代码的可移植性这一重要的特性,这对于我国程序设计环境的健康发展是相当不利的。本文通过讨论影响C++代码可移植性的一些因素,试图引导程序设计人员编写具有良好可移植性的C++程序。
2 影响C++程序可移植性的因素
2.1 非标准编译器的影响。C++语言从诞生到98标准诞生,花了整整15年的时间。在此期间,国际上一些跨国公司如Microsoft、IBM、Borland(如今的Inprise)相继开发了自己的C++编译器,这些公司的编译器除了包含标准的C++编译器的内容之外,还保留了自己的一些特性,甚至修改了部分标准。一旦程序设计人员使用了这些与C++标准不相符的功能,代码的可移植性将会成为一个大问题。例如对于在for循环中定义的变量的作用范围,遵循C++的98标准的Dev-C++编译器与国内流行的MS Visual C++编译器的解释便不一样。例如对于下面一段程序:
for ( int i=0;i 98标准规定,在for循环中定义的变量,其有效作用范围是for循环体,循环体结束后该变量的生命就结束了,因此,最后一条语句 int j = i; 对于i的访问是非法的。而MS Visual C++编译器则认为,即使是在for循环体中定义的变量,其作用范围也不仅仅局限于for循环体,而是和在其它地方定义的变量一样,一直到本函数结束,因此,上面例子中最后一条语句对于i的访问是合法的。
对于这种编译器不遵循国际标准的问题,笔者认为,MS Visual C++编译器等还是拥有相当大的用户群体的,不遵循它们的规则对我们提高程序的可移植性也是不利的。然而,首要的编程规则仍然是遵循国际标准化编码。
2.2 C语言的影响。很多从事C++程序设计的人员都是从C语言转移过来,C++语言的向下兼容性(即兼容C语言书写的源程序)使得这些程序设计人员很快的适应了C++程序的编写工作。然而,C++语言所倡导的面向对象程序设计方法和C语言的面向过程程序设计方法还是存在着很大区别的,尤其是面向对象要求对数据进行封装保护的机制在C语言中是不存在的。而从C语言转移过来的C++程序人员,却常常不经意地把C语言的风格和编程习惯带到了C++程序的编写当中。例如:在C语言中主函数main是可以没有返回值的,即返回值类型可以是void,而在C++标准中,明确要求主函数main必须返回int类型。再例如,C语言中人们习惯使用字符数组或字符指针来保存字符串如char name[30], char *str 等,而在C++中,提倡使用string 对象来替代字符数组的变量。
有人问及C++语言的创始人也是C++标准的制定者之一Bjarne Stroustrup博士,有没有想过删除一些C++语言的特性。Bjarne Stroustrup博士说:从语言设计的角度讲,我最不喜欢的部分是与C兼容的那个子集[2]。然而,出于对现实世界里工作的程序员的考虑,保留与C兼容的子集是有必要的,但这并不意味着我们要写出C风格的C++程序。
2.3 程序设计人员对国际标准的漠视。尽管编写C++程序不一定要百分百的遵循国际标准,笔者仍然认为,了解国际标准,并尽可能的遵循国际标准,有助于提高C++程序的可移植性。但是,国内程序设计人员甚少关注国际标准,很多程序员甚至不知道自己写出来的程序是否符合国际标准,通常情况下只是简单的将写出来的程序在某一特定编译器下编译测试通过就草草了事,导致自己所写出来的C++程序中充斥着大量的非标准代码。国际标准委员会为了让C++语言更好的实现面向对象程序设计的封装,在颁布的98标准中对原先提交的标准进行了一些修订,同时为了使得原有的程序不至于全部都要进行修改,保留了对原有标准的兼容性。例如头文件包含#include
这样的写法,在98标准中已经被废弃了,而改为使用不含.h的标准写法。
#include
原因之一是随着时间的推移,还能够继续支持.h的头文件包含的编译器将会越来越少,其次,标准写法在多个方面显示出了它的优越性,如对异常的捕获和处理、与其它C++标准类对象在接口方面的结合更紧密以及对本地化更好地支持,更为重要的一点是,iostream所定义的组件被声明为命名空间std的成员,而iostream.h定义的组件则被声明为全局的,不利于实现面向对象的封装性。然而,国内教材中却大量使用了前一种被废弃的写法。
2.4 国内教育界和出版界的影响。国内出版业的过分商业化导致出版的著作良莠不齐,特别是大量存在的高校教材,它们往往是程序设计人员入门的引导者。但是出版社对于教材的审查相对于其它专著来讲,又是比较放松的,导致了很多初学者养成了不好的编程习惯,写出了不规范的程序。而这种习惯一旦养成是很难纠正过来的。难怪Bjarne Stroustrup博士在谈到如何选择学习C++语言的书籍时说到:务必注意该书是否从一开始就讲授标准C++,并且矢志不渝地使用标准库机制[2]。例如,从输入中读取一个字符串应该是这样的:
string s;/*标准C++程序的风格*/cin>>s;
而不是这样的:char s[MAX];/*标准C程序的风格*/scanf(“%s”,s);
可惜,在国内很多C++语言教材中都采用了后者,完全符合C++标准的高校教材是少之又少。
3 问题的解决
造成C++程序设计人员写出不具备良好可移植性的代码的原因是多方面的,要解决这个问题,笔者认为,应该从以下几个方面入手:
3.1 选择标准化的C++编译器。标准化的C++编译器在编译非标准的C++代码时会给出警告信息,编译人员可以根据警告信息修改自己的代码,使之符合标准C++程序的编码风格。选择标准的C++编译器应该从高校教育开始,笔者认为,高校教育的导向是至关重要的,然而不幸的是,笔者了解到,尽管Ms Visual Studio2005的C++编译器已经遵循了C++的98标准[3],全国计算机等级考试C和C++语言所使用的编译环境却仍然最不遵循98标准的Ms Visual C++6.0。
3.2 提高专著尤其是教材出版者自身的素质。标准C++编译器不是万能的,例如上面所提到的for循环体中定义的变量存在的问题,是编译器没有办法检查出来的。作为知识的传播者,各类著作的编者应该努力学习本行业的相关标准,写出符合国际标准的代码,使之具有良好的可移植性。
3.3 提倡专著尤其是教材编写与标准化相接轨,规范这些著作的编写和出版。出版社应该组织权威的专家对准备出版的著作进行严格的审查,对不符合国际标准的写法予以纠正。这样才能保证程序设计人员在起步的时候就能主动的遵循国际标准。
参考文献
[1] Juan Soulie. History of C++. [2008-1-18]. http://www.cplusplus.com/info/history.html.
[2] Bjarne Stroustrup. Bjarne Stroustrup's FAQ. [2008-2-5]. http://www.research.att.com/~bs/bs_faq.html.
[3] Bradley L. Jones. Breaking Changes in Visual C++ 2005. http://www.developer.com/net/cplus/article.php/3493706.
收稿日期:2008-5-07
注:“本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。”
【关键词】 C++标准;可移植性;编译环境
【中图分类号】:G623.58【文献标识码】:B 【文章编号】:1009-9646(2008)05-0113-01
1983年第一个C++程序投入使用,1994年8月,ANSI/ISO委员会草案登记,这便是业内所称的早期的C++标准,1998年11月,ISO/IEC:98-14882标准(以下简称98标准)被批准,标志着C++代码的标准化正式诞生[1]。目前标准委员会正在修订C++标准,并拟于2009年发布修订后的09标准。可以预见,C++语言作为程序开发的主要工具仍将延续很长的一段时间。
C++语言诞生以来,延续了C语言的重要特征,即C++源程序良好的可移植性。正是这一特性,使得C/C++语言长期以来一直是程序开发人员的首选。然而,国内程序设计人员由于长期受到单一编译环境的影响,甚少关注C++代码的可移植性这一重要的特性,这对于我国程序设计环境的健康发展是相当不利的。本文通过讨论影响C++代码可移植性的一些因素,试图引导程序设计人员编写具有良好可移植性的C++程序。
2 影响C++程序可移植性的因素
2.1 非标准编译器的影响。C++语言从诞生到98标准诞生,花了整整15年的时间。在此期间,国际上一些跨国公司如Microsoft、IBM、Borland(如今的Inprise)相继开发了自己的C++编译器,这些公司的编译器除了包含标准的C++编译器的内容之外,还保留了自己的一些特性,甚至修改了部分标准。一旦程序设计人员使用了这些与C++标准不相符的功能,代码的可移植性将会成为一个大问题。例如对于在for循环中定义的变量的作用范围,遵循C++的98标准的Dev-C++编译器与国内流行的MS Visual C++编译器的解释便不一样。例如对于下面一段程序:
for ( int i=0;i
对于这种编译器不遵循国际标准的问题,笔者认为,MS Visual C++编译器等还是拥有相当大的用户群体的,不遵循它们的规则对我们提高程序的可移植性也是不利的。然而,首要的编程规则仍然是遵循国际标准化编码。
2.2 C语言的影响。很多从事C++程序设计的人员都是从C语言转移过来,C++语言的向下兼容性(即兼容C语言书写的源程序)使得这些程序设计人员很快的适应了C++程序的编写工作。然而,C++语言所倡导的面向对象程序设计方法和C语言的面向过程程序设计方法还是存在着很大区别的,尤其是面向对象要求对数据进行封装保护的机制在C语言中是不存在的。而从C语言转移过来的C++程序人员,却常常不经意地把C语言的风格和编程习惯带到了C++程序的编写当中。例如:在C语言中主函数main是可以没有返回值的,即返回值类型可以是void,而在C++标准中,明确要求主函数main必须返回int类型。再例如,C语言中人们习惯使用字符数组或字符指针来保存字符串如char name[30], char *str 等,而在C++中,提倡使用string 对象来替代字符数组的变量。
有人问及C++语言的创始人也是C++标准的制定者之一Bjarne Stroustrup博士,有没有想过删除一些C++语言的特性。Bjarne Stroustrup博士说:从语言设计的角度讲,我最不喜欢的部分是与C兼容的那个子集[2]。然而,出于对现实世界里工作的程序员的考虑,保留与C兼容的子集是有必要的,但这并不意味着我们要写出C风格的C++程序。
2.3 程序设计人员对国际标准的漠视。尽管编写C++程序不一定要百分百的遵循国际标准,笔者仍然认为,了解国际标准,并尽可能的遵循国际标准,有助于提高C++程序的可移植性。但是,国内程序设计人员甚少关注国际标准,很多程序员甚至不知道自己写出来的程序是否符合国际标准,通常情况下只是简单的将写出来的程序在某一特定编译器下编译测试通过就草草了事,导致自己所写出来的C++程序中充斥着大量的非标准代码。国际标准委员会为了让C++语言更好的实现面向对象程序设计的封装,在颁布的98标准中对原先提交的标准进行了一些修订,同时为了使得原有的程序不至于全部都要进行修改,保留了对原有标准的兼容性。例如头文件包含#include
这样的写法,在98标准中已经被废弃了,而改为使用不含.h的标准写法。
#include
原因之一是随着时间的推移,还能够继续支持.h的头文件包含的编译器将会越来越少,其次,标准写法在多个方面显示出了它的优越性,如对异常的捕获和处理、与其它C++标准类对象在接口方面的结合更紧密以及对本地化更好地支持,更为重要的一点是,iostream所定义的组件被声明为命名空间std的成员,而iostream.h定义的组件则被声明为全局的,不利于实现面向对象的封装性。然而,国内教材中却大量使用了前一种被废弃的写法。
2.4 国内教育界和出版界的影响。国内出版业的过分商业化导致出版的著作良莠不齐,特别是大量存在的高校教材,它们往往是程序设计人员入门的引导者。但是出版社对于教材的审查相对于其它专著来讲,又是比较放松的,导致了很多初学者养成了不好的编程习惯,写出了不规范的程序。而这种习惯一旦养成是很难纠正过来的。难怪Bjarne Stroustrup博士在谈到如何选择学习C++语言的书籍时说到:务必注意该书是否从一开始就讲授标准C++,并且矢志不渝地使用标准库机制[2]。例如,从输入中读取一个字符串应该是这样的:
string s;/*标准C++程序的风格*/cin>>s;
而不是这样的:char s[MAX];/*标准C程序的风格*/scanf(“%s”,s);
可惜,在国内很多C++语言教材中都采用了后者,完全符合C++标准的高校教材是少之又少。
3 问题的解决
造成C++程序设计人员写出不具备良好可移植性的代码的原因是多方面的,要解决这个问题,笔者认为,应该从以下几个方面入手:
3.1 选择标准化的C++编译器。标准化的C++编译器在编译非标准的C++代码时会给出警告信息,编译人员可以根据警告信息修改自己的代码,使之符合标准C++程序的编码风格。选择标准的C++编译器应该从高校教育开始,笔者认为,高校教育的导向是至关重要的,然而不幸的是,笔者了解到,尽管Ms Visual Studio2005的C++编译器已经遵循了C++的98标准[3],全国计算机等级考试C和C++语言所使用的编译环境却仍然最不遵循98标准的Ms Visual C++6.0。
3.2 提高专著尤其是教材出版者自身的素质。标准C++编译器不是万能的,例如上面所提到的for循环体中定义的变量存在的问题,是编译器没有办法检查出来的。作为知识的传播者,各类著作的编者应该努力学习本行业的相关标准,写出符合国际标准的代码,使之具有良好的可移植性。
3.3 提倡专著尤其是教材编写与标准化相接轨,规范这些著作的编写和出版。出版社应该组织权威的专家对准备出版的著作进行严格的审查,对不符合国际标准的写法予以纠正。这样才能保证程序设计人员在起步的时候就能主动的遵循国际标准。
参考文献
[1] Juan Soulie. History of C++. [2008-1-18]. http://www.cplusplus.com/info/history.html.
[2] Bjarne Stroustrup. Bjarne Stroustrup's FAQ. [2008-2-5]. http://www.research.att.com/~bs/bs_faq.html.
[3] Bradley L. Jones. Breaking Changes in Visual C++ 2005. http://www.developer.com/net/cplus/article.php/3493706.
收稿日期:2008-5-07
注:“本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。”