- Visual C++程序设计与项目实践
- 安金梁 范秀平主编
- 2027字
- 2020-08-27 02:54:48
1.5 Visual C++ 6.0编写的程序转化到Visual C++ 2008中的方法
由于VC++6.0版本的广泛使用,使得以前很多优秀的代码都是使用VC++6.0编写的;同时,VC++2008相对于对VC++6.0做了很大的改进,应用程序的安全性和效率有了很大的提高。为了同时有效地利用VC++6.0众多优秀的源代码和VC++2008编译环境的重大改进,介绍VC++6.0到VC++2008的转换方法显得特别重要。
由于本节内容有一定难度,初学者可以跳过本节,等学完本书全部内容再学习本节。也可以先读一遍本节,带着问题去读本书下面的章节。
1.5.1 多字节字符集和Unicode字符集
在计算机中字符通常并不是保存为图像,每个字符都是使用一个编码来表示的,而每个字符究竟使用哪个编码代表,要取决于使用哪个字符集(charset)。
在最初的时候,Internet上只有一种字符集——ANSI的ASCII字符集,它使用7b来表示一个字符,总共表示128个字符,其中包括了英文字母、数字、标点符号等常用字符。之后,又进行扩展,使用8b表示一个字符,可以表示256个字符,主要在原来的7b字符集的基础上加入了一些特殊符号例如制表符。
后来,由于各国语言的加入,ASCII已经不能满足信息交流的需要,因此,为了能够表示其他国家的文字,各国在ASCII的基础上制定了自己的字符集,这些从ANSI标准派生的字符集被习惯的统称为ANSI字符集,它们正式的名称应该是MBCS(Multi-Byte Chactacter System,即多字节字符系统)。由于每种语言都制定了自己的字符集,导致最后存在的各种字符集实在太多,在国际交流中要经常转换字符集非常不便。因此,提出了Unicode字符集,它固定使用16b(两个字节、一个字)来表示一个字符,总共可以表示65536个字符。将世界上几乎所有语言的常用字符收录其中,方便了信息交流。标准的Unicode称为UTF-16。后来为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8,使用类似MBCS的方式对Unicode进行编码。
在Visual Studio 2005以前版本的Visual Studio默认使用多字节字符集,而Visual Studio 2005、Visual Studio 2008默认使用Unicode字符集。如果您的代码必须要借助以前版本的VC++编写的代码,可以采用两种方法将VC++6.0中的代码加入到VC++2008中:
1. 将VC++6.0中的ANSI字符和字符串换成Unicode形式,并使用相应的字符和字符串操作方法。对于初学者来说该方法难度较大。
2. 设置VC++2008参数,将应用程序工程的属性从“使用Unicode字符集”改为“使用多字节字符集”。该方法使用起来非常简单。
将应用程序工程的属性从“使用Unicode字符集”改为“使用多字节字符集”的方法是:假如我们对VC++2008中创建的工程“ProgramChapt0102”进行方法2的设置,我们只需在菜单“项目”中鼠标左击选择“ProgramChapt0102属性”菜单项,就会弹出如图1-8所示的窗口。在“配置属性”的“常规”项中,将“字符集”改为“使用多字节字符集”即可。
图1-10 VC++2008中使用多字节字符集的设置方法
1.5.2 安全函数
首先举个例子,在VC++6.0中编译下面的语句:
图1-11 strcpy示例代码
结果是没有错误和警告。
但是在Visual C++ 2008中编译上面的语句,就会出现如图1-12所示的警告:
图1-12 Visual C++ 2008中关于安全函数的警告
在Visual C++ 2008中,CRL(C Runtime Library)中的一组函数已不再建议使用,而应使用新提供的安全版本。大多数这些不建议使用的函数如果使用不当,将会导致缓冲区溢出或其他安全问题,这些函数如:strcpy、strcat等等。这些函数新的安全版本都在函数名后加了一个_s后缀,以方便识别,如strcpy_s、wcscpy_s、mbscpy_s、calloc_s和strcat_s等。
去除图1-12所示的警告的方法有两种:
1. 继续使用老版本、非安全的函数,在预编译头文件stdafx.h里(注意:一定要在没有include任何头文件之前)定义下面的宏:
#define _CRT_SECURE_NO_DEPRECATE
或者
#pragma warning(disable:4996)
2. 使用新的安全函数代替旧的不安全的函数。
我们不建议使用方法1,因为非安全函数的不当使用会导致缓冲区溢出或其他安全问题,而这些安全问题很可能会使应用程序崩溃。比如我们将图1-11中的代码改为图1-13所示,即buf2的大小改为4个字节,而buf1占用的内存大小为6个字节(5个字符加上一个"\0"结尾标志),此时buf2的空间小于buf1的空间。在Visual C++6.0下编译时不会出错,但是在Release状态下运行时会使程序崩溃,如图1-15所示。
图1-13 strcpy函数缓冲区溢出错误示例代码
图1-14 strcpy_s函数缓冲区溢出错误示例代码
图1-15 strcpy缓冲区溢出错误造成Visual C++6.0程序崩溃
但如果我们使用Visual C++ 2008编译如图1-14所示的代码,在"Release"方式下编译,就会出现如图1-16所示的警告:
图1-16 strcpy_s函数缓冲区溢出时Visual C++ 2008编译器发出警告信息
从上面分析可以看到,使用安全函数是Visual C++ 2008相对于Visual C++6.0的一个巨大的改进。
1.5.3 Visual C++ 2008相对于VC++6.0的其他改进
Visual C++ 2008相对于VC++6.0还有其他方面的改进,在使用Visual C++ 2008进行编程时,也要留意这些变化。对初学者来说,主要有以下方面需要注意:
1. 参数的有效性
Visual C++ 2008在C运行时库中加入了一些代码,以检查参数的有效性。例如:如果传递的目标缓冲区大小不足以strcpy使用,此时则会调用一个非法参数处理程序。
2. 迭代器越界
迭代器因为安全的原因进行了相应的更新,如果迭代器越界,则相应会调用一个非法参数处理程序。
3. time_t类型
time_t类型通常用于显示从1970年开始以来的秒数。直到Visual C++ 7.1(即Visual C++ .NET 2003),time_t类型都被定义为一个long,而到了Visual C++ 2005和Visual C++ 2008中,已被定义为一个64位类型,可用于显示一直到3000年的时间了。
4. 范围限制规则
在for循环声明中,默认情况下不强制执行范围限制规则。在之前的版本中,for循环中变量的生命期将会延续到循环之外,为与标准兼容,for循环中定义的变量,现在只限定在for循环内使用。