选择显示字体大小

新时代的门前 32位世界中的64位编程

为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;
}

  (b)

struct sockaddr_in saddrin
char *str;

if (.net_aton(str, &saddrin.sin_addr) ! = ok) {
 do_some_error_handling;
}

  因为只要.net_addr能够正确地解析字符串,那么一切ok。当.net_addr在64位计算机上返回一个错误时,这段代码却未能捕捉到。你必须要考虑比较语句中的数据位宽,来确定到底是哪出了错。

  首先,.net_addr返回错误值——unsigned long -1,在64位中表示为比特位全为1,这个值被存储在结构in_addr下的子域s_addr中,而in_addr必须是32位来匹配inte.net地址,所以它是一个32比特位的unsigned int(在我们的编译器上,int是64位)。现在我们存储进32个1,存储进的值将与unsigned long -1比较。当我们存储32个1于unsigned int时,编译器自动把32位提升为64位;这样,数值0x00000000 ffffffff与0xffffffff ffffffff的比较当然就失败了。这是一个很难发现的bug,特别是在这种因为32位到64位的隐式提升上。

  那我们对这个bug怎么办呢?一个解决方法是在语句中比较0xffffffff,而不是-1,但这又会使代码更加依赖于特定大小的对象。另一个方法是,使用一个中间的unsigned long变量,从而在把结果存入sockaddr_in前,执行比较,但这会让程序代码更复杂。

  真正的问题所在是,我们期望一个unsigned long值与一个32位量(如inte.net地址)相等。inte.net地址必须以32位形式进行存储,但有些时候用一个标量,来访问这个地址的一部分,是非常方便的。在32位字长的电脑中,用一个long数值(常被当作32位)来访问这个地址,看上去没什么问题。让我们暂时不想一个低级的数据项(32位inte.net地址)是否与一个机器字相等,那么高级数据类型结构in_addr就应该被一直使用。因为in_addr中没有无效值,那么应有一个单独的状态用作返回值。

  解决方案是定义一个新的函数,就像.net_addr那样,但返回一个状态值,而且接受一个结构in_addr作为参数,参见例1(b)。因为高级的数据元素可以一直使用,而返回的值是没有溢出的,所以这个代码是可以跨架构移植的,而不管字长是多少。虽然伯克利发布.net2,其中的确定义了一个新的函数.net_aton(),但如果试着改变.net_addr()中的代码,将会损坏许多程序。

  低级代码的低级结构

  低级编程意味着直接操纵物理设备或者特定协议的通讯格式,例如,设备驱动程序经常使用非常精确的位模式来操纵控制寄存器。此外,网络协议通过特定的比特位模式传输数据项时,也必须适当地转译。

  为了操纵物理数据项,此处的数据结构必须准确地反映被操纵的内容。比特位是一个不错的选择,因为它们正好指定了比特的位数及排列。事实上,正是这种精确度,使比特位相对于short、int、long,更好地映像了物理结构(short、int、long会因为电脑的不同而改变,而比特位不会)。

  当映像一个物理结构时,是通过定义格式来使比特位达到这种精度的,这就使你必须一直使用一种编码风格来访问结构。此时的每个位域都是命名的,你写出的代码可直接访问这些位域。当访问物理结构时,有件事可能你并不想去做,那就是使用标量数组(short、int、or long),访问这些数组的代码都假定存在一个特定的比特位宽,当移植这些代码到一台使用不同字宽的电脑上时,就可能不正确了。

  在我们移植pex图像库时遇到的一个问题,就涉及到其映像的协议消息结构。在某台电脑上,如果int整型的长度与消息中的元素一样,那例2(a)中的代码就会工作得很正常。32位的数据元素在32字长的电脑上没有问题,拿到64位的克雷计算机上,它就出错了。对例2(b)而言,不单要改变结构定义,还要改变所有涉及到coord数组的代码。这样,摆在我们面前就有两个选择,要么重写涉及此消息的所有代码,要么定义一个低级的结构和一个高级的结构,然后用一段特殊的代码把数据从一个拷贝到另一个当中,不过我也不期望可以找出每个对zcoord = draw_ msg.coord[2]的引用,而且,当现在需要移植到一个新架构上时,把所有的代码都改写成如例2(c)所示无疑是一项艰苦的工作。这个特殊的问题是由于忽视字长的不同而带来的,所以不能假设在可移植的代码中机器字长、short、int、long都是具有同样的大小。

  例2:低级代码的低级结构

  (a)

struct draw_msg {
 int objectid;
 int coord[3];
}

  (b)

struct draw_msg {
 int objectid:32;
 int coord1:32;
 int coord2:32;
 int coord3:32;
}

  (c)

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   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons