为16、32、64位架构编写可移植代码
与16位相比,32位意味着程序更快、可直接寻址访问更多的内存和更好的处理器架构。鉴于此,越来越多的程序员已经开始考虑利用64位处理器所带来的巨大优势了。
克雷研究(cray research 应为品牌名)计算机已经开始使用64位字,并可访问更大的内存地址。然而,作为正在向开发标准软件和与其他操作系统相互努力的一部分,我们已经停止了移植那些原本基于32位处理器的代码。事实上,我们不断遇到我们称之为“32位主义”的代码,这些代码都是在假定机器字长为32位的情况下编写的,因而很难移植这种代码,所以必须确立一些简单的指导方针,以便助于编写跨16、32、64位处理器平台的代码。
由于有一些遗留问题,c语言在数据类型和数据构造方面,显得有点过剩了。可以使用的不仅仅是char、short、int和long类型,还有相应的unsigned(无符号)类型,当然你可在结构(structure)和联合(union)中混合使用,可以在联合中包含结构,再在结构中包含联合,如果还嫌数据类型不够复杂,还可以转换成比特位,当然也可以把一种数据类型转换成另一种你想要的数据类型。正是因为这些工具太强大,如果不安全地使用它们,就有可能会伤到自己了。
高级代码的高级结构
在kernighan和plauger经典的《the elements of programming style》一书中,他们的建议是“选择使程序看上去简单的数据表示法”。对个人而言,这意味着为高级编程使用高级数据结构,而低级编程使用低级数据结构。
在我们移植的程序中,有一个常见的32位主义bug,不如拿它来做个例子,科内尔大学编写的用于网间互访的路由协议引擎,在伯克利网络环境下(指tcp/ip),自然是使用.net_addr( )来把表示inte.net地址的字符串转换成二进制形式。inte.net地址碰巧也是32位的,就如运行伯克利网络系统的其他计算机一样,都是有着同样的字宽。
但也存在着有关inte.net地址的高级定义:in_ addr结构。这个结构定义包括了子域s_ addr,它是一个包含了inte.net地址的unsigned long标量。.net_addr()接受一个指向字符的指针,并且返回一个unsigned long,在转换地址字符串过程中如果发生错误,.net_addr将返回-1。
程序gated读取以文本格式存放inte.net地址的配置文件,并把它们放入sockaddr_in(这是一个包含了结构in_addr的高级结构)。例1(a)中的代码可以在32位电脑上正常运行,但移植到克雷研究计算机上,却无法运行,为什么呢?
例1:高级代码的高级结构
(a)
| struct sockaddr_in saddrin char *str; if ((saddrin.sin_addr.s_addr = .net_addr(str)) == (unsigned long)-1) { do_some_error_handling; } |
| struct sockaddr_in saddrin char *str; if (.net_aton(str, &saddrin.sin_addr) ! = ok) { do_some_error_handling; } |
| struct draw_msg { int objectid; int coord[3]; } |
| struct draw_msg { int objectid:32; int coord1:32; int coord2:32; int coord3:32; } |
| int *iptr, *optr, *limit; int xyz[3]; iptr = draw_msg.coord; limit = draw_msg.coord + sizeof(draw_msg.coord); optr = xyz; while (iptr < limit) *optr++ = *iptr++; |
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器