`
shi5jin
  • 浏览: 37179 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

站在巨人肩上的思考[连载] (6)

阅读更多
 

4 类型和声明

4.3 字符类型

       “由8bits表示的256个值可以解释为0~255,或者解释为-128~127,不幸的是,普通char类型选择那种解释是由具体实现决定的”[1]<o:p></o:p>

       所以,不要做过多的假设。如果你必须这样做,请使用显式的signed char或者unsigned char来声明变量。

4.4整数类型

unsigned整数类型对于存储二进制bit数组的使用方式非常理想。但是,如果用unsigned而不用int仅仅因为想多一个bit来表示正整数,就不是什么好主意。”[2]<o:p></o:p>

       这句话轻描淡写的一笔带过,但是含义颇深。它再一次提醒我们,不要指望一种并没有看起来那么可靠的措施,来为我们提供安全保险。

举例来说,当我们声明一个如下的函数:

       int func(unsigned arg)

的时候,其实我们的潜台词是:“哦,我要的参数的值都应该是大于零的。”不幸的是,事实的确如此。对于函数内部,arg肯定是大于0。那为什么危险?因为我们认为这种声明方式会给我带来某种类型安全,却恰恰相反。C++intunsigned提供了隐式转换,这意味着一个负整数可以悄无声息的在需要的时候变为一个正整数。假设程序由于某种异常调用了func(-1),此时在func()内部arg的值就可能是4294967295(在我的32PC上)或者是一个其他的正整数值,函数将正常执行,甚至返回一个表示成功的值,但是其实际结果可能完全不是那么回事!程序将由此“驶上通往崩溃的快车道”。另一方面,正是由于声明时的潜台词,我们通常忽略了接口输入参数的安全检查,而交给unsigned类型这个脆弱的保护措施,况且,当我们使用了unsigned做声明的时候,我们也根本无法进行必要的安全检查,应为arg在函数内部一定为正!或者有些人依然会狡辩说,可以针对特定应用,来收紧检查条件,如月份我们可以检查if(arg>0 && arg<13)。请相信我,即使是说这话的人本身也会底气不足的,因为调用者完全可以传递一个负数,使得在函数内部的参数值落在安全范围之内。虽然概率很小,但是对于一个健壮的程序来说,这是不允许的。想想坐在屏幕前看着一些充满了magic number的调试信息,用整个下午的时间猜测每个数字是怎么来的情景,那种痛苦真是会令人崩溃。如果你不想成为这样可怜的程序员,请注意这个细节:大多数时候尽量使用signed而不是unsigned类型,尤其是作为函数接口的时候,并且做好每一次接口安全检查。终有一天你会发现,花费这点力气是值得的。

4.6 类型的大小

       很多时候,清楚地知道每种类型的大小是有实际意义的。这点对于固定平台的程序员来说可能不是那么明显,但是对于那些经常更换目标平台的嵌入式程序员来说,就很实际了。况且,即便是前者,也应该意识到,任何一个成功的软件,几乎都面临着跨平台的考验。一个有远见的程序员,应该从开始就注重这些细节。

       C++对象的大小,使用char的大小的整数倍来表示的”。有些平台对char的实现并不一定用8bit,还有些实现int也不一定是32bit。不要对类型大小以及相互之间的关系做某种过多的假设。书上第四段列出了一些“肯定”的关系,除次之外的其他结论都是不稳固的。另外,C++也提供了专门研究类型大小、边界的库,可通过标准头文件 <limits></limits> 来调用。具体内容可参见库使用说明,这里提供一个很丑的示范程序,你可以直接拷贝到你的平台上,编译,运行,“挑战一下极限”。

  1. #include <iostream>  
  2. #include <cstdlib>  
  3. #include <limits> // numeric_limits   
  4. #include <string>   
  5. using namespace std;   
  6.   
  7. void isSpecialized(void);   
  8. void hasInfinity(void);   
  9. void getMaxValue(void);   
  10. void getMinValue(void);   
  11. void getEpsilon(void);   
  12. void howManyDigits10(void);   
  13. void howManyDigits2(void);   
  14.   
  15. int main()   
  16. {   
  17.   ///whether the internal type has a max or min value:   
  18.   isSpecialized();   
  19.   ///whether has a infinite value;   
  20.   hasInfinity();   
  21.   ///what's the max value of a type;   
  22.   getMaxValue();       
  23.   ///what's a min value of a type;   
  24.   getMinValue();   
  25.   //what's the min value of a float type.   
  26.   getEpsilon();   
  27.   //how many decimal digits can a type express;   
  28.   howManyDigits10();   
  29.   //how many binary digits can a type express;   
  30.   howManyDigits2();   
  31.        
  32.   return 0;   
  33. }   
  34.   
  35. void  
  36. isSpecialized(void) {   
  37.   cout << boolalpha;   
  38.   cout << "specialized(char): "  << numeric_limits<char>::is_specialized << endl;   
  39.   cout << "specialized(wchar_t): "  << numeric_limits<wchar_t>::is_specialized << endl;    
  40.   cout << "specialized(string): "  << numeric_limits<string>::is_specialized << endl;   
  41.   cout<< noboolalpha;   
  42.           
  43.   return;       
  44. }   
  45.   
  46. void  
  47. hasInfinity(void) {   
  48.   cout << boolalpha;   
  49.   cout << "has infinity char: " << numeric_limits<char>::has_infinity << endl;   
  50.   cout << "has infinity long double: "  << numeric_limits<long double>::has_infinity << endl;   
  51.   cout << "has infinity string: "  << numeric_limits<string>::has_infinity<< endl;   
  52.   cout << noboolalpha << endl;   
  53.      
  54.   return ;   
  55. }   
  56.   
  57. void  
  58. getMaxValue(void) {   
  59.   cout << "max(int): "    
  60.        << numeric_limits<int>::max()   
  61.        << "\nmax(char): "  
  62.        << static_cast<int>(numeric_limits<char>::max())   
  63.        << "\nmax(short): "  
  64.        << numeric_limits<short>::max()   
  65.        << "\nmax(unsigned int): "    
  66.        << numeric_limits<unsigned int>::max()   
  67.        << "\nmax(unsigned short): "    
  68.        << numeric_limits<unsigned short>::max()   
  69.        << "\nmax(unsigned long): "    
  70.        << numeric_limits<unsigned long>::max()   
  71.        << "\nmax(long): "    
  72.        << numeric_limits<long>::max()   
  73.        << "\nmax(long long): "    
  74.        << numeric_limits<long long>::max()   
  75.        << "\nmax(float): "    
  76.        << numeric_limits<float>::max()   
  77.        << "\nmax(double): "    
  78.        << numeric_limits<double>::max()   
  79.        << "\nmax(long double): "    
  80.        << numeric_limits<long double>::max()   
  81.        << endl;   
  82.      
  83.   return ;   
  84. }   
  85.   
  86. void  
  87. getMinValue(void) {   
  88.   cout << "min(int): "    
  89.        << numeric_limits<int>::min()   
  90.        << "\nmin(char): "    
  91.        << static_cast<int>(numeric_limits<char>::min())   
  92.        << "\nmin(short): "    
  93.        << numeric_limits<short>::min()   
  94.        << "\nmin(unsigned int): "    
  95.        << numeric_limits<unsigned int>::min()   
  96.        << "\nmin(unsigned short): "    
  97.        << numeric_limits<unsigned short>::min()   
  98.        << "\nmin(unsigned long): "    
  99.        << numeric_limits<unsigned long>::min()   
  100.        << "\nmin(long): "    
  101.        << numeric_limits<long>::min()   
  102.        << "\nmin(long long): "    
  103.        << numeric_limits<long long>::min()   
  104.        << "\nmin(float): "    
  105.        << numeric_limits<float>::min()   
  106.        << "\nmin(double): "    
  107.        << numeric_limits<double>::min()   
  108.        << "\nmin(long double): "    
  109.        << numeric_limits<long double>::min()   
  110.        << endl;   
  111.          
  112.   return ;   
  113. }   
  114.   
  115. void  
  116. getEpsilon(void) {   
  117.   cout << "\ndouble epsilon: "    
  118.        << numeric_limits<double>::epsilon()    
  119.        << "\nfloat epsilon: "    
  120.        << numeric_limits<float>::epsilon()   
  121.        << "\nlong double epsilon: "    
  122.        << numeric_limits<long double>::epsilon()   
  123.        << endl;   
  124. }   
  125.   
  126. void  
  127. howManyDigits10(void) {   
  128.   cout << "\ndouble dec digits number: "  
  129.        << numeric_limits<double>::digits10   
  130.        << "\nfloat dec digits number: "  
  131.        << numeric_limits<float>::digits10   
  132.        << "\nlong double dec digits number: "  
  133.        << numeric_limits<long double>::digits10   
  134.        << "\nlong long dec digits number: "  
  135.        << numeric_limits<long long>::digits10   
  136.        << "\nint dec digits number: "  
  137.        << numeric_limits<int>::digits10   
  138.        << "\nshort dec digits number: "  
  139.        << numeric_limits<short>::digits10   
  140.        << "\nchar dec digits number: "  
  141.        << numeric_limits<unsigned char>::digits10   
  142.        <<endl;   
  143.           
  144.   return ;   
  145. }   
  146.   
  147. void  
  148. howManyDigits2(void) {   
  149.   cout << "\ndouble dec digits number: "  
  150.        << numeric_limits<double>::digits   
  151.        << "\nfloat dec digits number: "  
  152.        << numeric_limits<float>::digits   
  153.        << "\nlong double dec digits number: "  
  154.        << numeric_limits<long double>::digits   
  155.        << "\nlong long dec digits number: "  
  156.        << numeric_limits<long long>::digits   
  157.        << "\nint dec digits number: "  
  158.        << numeric_limits<int>::digits   
  159.        << "\nshort dec digits number: "  
  160.        << numeric_limits<short>::digits   
  161.        << "\nchar dec digits number: "  
  162.        << numeric_limits<unsigned char>::digits   
  163.        <<endl;   
  164.           
  165.   return ;   
  166. }   
c# 代码

 



[1] The C++ Programming Language-- Chapter 4.3, paragraph 4

[2] The C++ Programming Language-- Chapter 4.4, paragraph 2

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics