快速业务通道

浅谈Unix和Linux下的int

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-04-21
indows的变量类型多,程序员学习的时候,成本高,但是,学会了就不容易出错.而Unix的学习曲线低,没那么多类型名要去背,不过呢,用起来出不出错,自理啊,Unix的开发者,相信大家的实力.嗯,只是我自己有点信不过我自己,嘿嘿. 不过要我说呢,还真说不好谁对谁错,其实都有道理,关键看OS的设计者,心目中的目标用户的水平如何了. 回到和平同学的问题,用int,少一半,其实是有道理的,int是有符号的,有一半的表示范围是负数,在表示很多容量的时候,比如说吧,malloc的数组,或者socket的表示范围,确实负数没有意义.因此,看起来被浪费了. 这其实不然,为什么,原因很简单. int就算少一半,你能用多少?和平同学别见怪啊,我说句话,你问这个问题就表示还有点学生思维,总是想多多益善,就是我要把所有的资源都纳入我的管理,呵呵.其实我们做工作做久了的,对于数据的边界、范围,反而有个思想,够用就好,没必要多. int表示少一半,2G有吧,嗯,大多数用户的数组,可不可能超过1G?其实,大多数时候,我们在这个地方用int,表示的范围都很少的.少一半也够用.socket不说了吧,理论上只有65536,int再少几半也够用,呵呵. 够用就行了,不用担心的,真要是需要用大表示,自己做unsigned long来表示,也是可以的. ,Unix这么设计,有个最大的优点,就是数据的自描述特性得到了前所未有的发挥.我们都知道,在表示范围、容量的时候,int只使用了正数部分,那负数部分做什么?我来回答你,表示非法值,这个很重要. 试想一下,如果我们用的数据类型里面,无法表示非法值,那麻烦了,api设计的时候,单独设计一个参数,来传递非法值,这又涉及到&传址调用,或者*直接传指针调用,程序设计复杂度直线上升,设计的人也累,学的人也累,用起来更累. 这么说可能不直观,我举个例子: 比如我要设计一个read函数,从某个文件id读取一段数据,大家注意啊,Unix下,文件ID可以表示任何串行化设备的.包括socket,可以用resv这类伯克利socket api,也可以直接使用C基本库的read,都对,使用int表示,Unix可以把所有串行化设备统一编址处理,用一类函数处理完. 函数原型我这么设计,设计了两个,大家比较一下: Code:
  1. int ReadFrom(int fd,char* szBuffer,int nBufferSizeMax);
  2. unsigned int ReadFrom(int fd,char* szBuffer,int nBufferSizeMax);
可以吧,这虽然用了匈牙利命名法,但是,这是标准的C函数,没错吧.嗯,第一个应该是Unix的习惯,用int,第二个应该是Windows的习惯,用了无符号正整数,好,我们来看一种情况. 如果我们读失败了,要返回一个错误信息给上层调用者,怎么办? 第一个很简单,其只使用了int的正数部分来表示读成功多少字节,那好,-1来表示失败就好了. 第二个就麻烦了,它只返回正整数,上层看见都都是对的,它没有办法返回一个错误标示.说白了,这个api设计很失败,无法满足所有的应用返回需求.那怎么办?也有两种做法: Code:
  1. unsigned int ReadFrom(int fd,char* szBuffer,int nBufferSizeMax,bool& bSuccessFlag);
  2. #define READ_FAIL 0xFFFFFFFF
  3. //出错返回READ_FAIL
  4. unsigned int ReadFrom(int fd,char* szBuffer,int nBufferSizeMax);
大家别说用0啊,很多时候,Read到0,不是错误,是一种正常的状态,比如socker的read,read到0Bytes,很可能是对方没有发送,并不是说socket失败了,需要重建链路. 嗯,大家再来看看,第一种,没办法,只有多设计一个传址的参数,让函数返回是否成功读取的标志,上层来决定怎么处理. 第二种呢,显式定义一个返回值为错误,这个返回值永远不被理解为正确的值,就是正确业务不使用,仅供返回错误. 大家去比较一下Win32api,里面很多用的都是第二种方法. 不过,这样一来,大家觉得麻烦不麻烦,第一种,起码要多做一个参数,程序员学习量增加,记住哦,一个函数好学,100个、1000个函数让你背,你就觉得这个bSuccessFlag很讨厌了. 第二个更无礼,,它限制了业务,导致了业务缺陷,至少,unsigned int表示的最大值,被用来做fail了,就是业务不能用了,其次,多了个宏,同样的返回值unsigned int,需要区别对待,大家说用起来麻烦不麻烦? 别怕麻烦啊,呵呵,去看看Win32Socket的函数,它的SOCKET就是用了unsigned int表示的最大值,作为错误的SOCKET标识,其实就是按照上面第二种办法设计的api,没办法,谁让他把SOCKET定义为无符号正整数呢.自己给自己下绊子,呵呵. 嗯,还有什么beginthreadex,CreateWindowsEx,这类函数,大家去看看HANDLE的数据定义,就知道为什么参数设计得那么繁琐了. 很多时候,我们看api好用不好用,其实就看这些细节. 这里多说一点吧,正是Unix和Linux下,很多api函数都用int做返回值,-1已经被公认为非法,失败的标志,大家用起来反而简单,一般说来,看见一个Unix的api函数,猜都猜得出它怎么表示返回值,反正都是int嘛,-1就是失败啦,0和正数都是成功.Windows下就麻烦了,查MSDN都要查半天,主要看它数据类型,以及相应的接口定义. 因此,别看Windows做了很多努力,做了很多程序员友好度的工作,有时候啊,我评论一句,还真不如Unix什么都丢给程序员. 不过呢,也不好都说不对,如果应用程序员不是计算机界的专业人士,比如说,一个其他专业的工程师,需要临时写一小段程序解决个问题,Windows能保证他不出错.为啥,数据类型定义错了,编译都过不去,自己查MSDN去. ,说来说去,我认为这个问题还是一个文化问题,两种平台的开发文化,导致了今天的局面.说不上谁好谁坏. 大家看着用吧. 嗯,我私人呢,喜欢Windows的匈牙利命名法,喜欢严谨的定名,但是,不是很喜欢它那么多数据类型,还是喜欢int,呵呵. 很多时候,我设计的api大家觉得有点怪,其实就来自于此,又用Windows的命名法,但是,api函数参数设计却更靠Unix一些,算两面的综合吧. 《0bug-C/C 商用工程之道》里面,我的工程库用的就是我的习惯,两种风格兼而有之,我觉得,不管白猫黑猫,抓到耗子就是好猫,哪个地方合用用哪个,哪个办法合用用哪个,没什么门户之见的. 这不绝对啊,上述仅仅是我个人的习惯,大家还是自己选合用的办法好了,没必要和我一样. =======================================================
在线底价购买《0bug-C/C 商用工程之道》
(直接点击下面链接或拷贝到浏览器地址栏)
http://s.click.taobao.com/t_3?&p=mm_13866629_0_0&n=23&l=http://search8.taobao.com/browse/0/n-g,orvv64tborsvwmjvgawdkmbqgboq---g,gaqge5lhebbs6qzlfmqmttgtyo42jm6m22xllqa-------------1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20---40--coefp-0-all-0.htm?pid=mm_13866629_0_0 肖舸

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号