当前位置:天才代写 > tutorial > C语言/C++ 教程 > C++ Builder 2010荟萃类的一个BUG

C++ Builder 2010荟萃类的一个BUG

2017-11-02 08:00 星期四 所属: C语言/C++ 教程 浏览:413

本日用C++ Builder 2010写一段小代码,用到了荟萃类,可荟萃运算功效怎么也差池,解除了其它原因,最后确定应该是荟萃类源代码的问题,下面是一段荟萃类的测试代码:

enum TTest{tt0, tt15 = 15, tt16 = 16};  
typedef Set<TTest, tt0, tt16> TTests;  
      
void __fastcall TForm1::Button1Click(TObject *Sender)  
{  
    TTests t1 = TTests() << tt15;  
    TTests t2 = TTests() << tt16;  
      
    ShowMessage(t1.ToInt());    // 32768  
    ShowMessage(t2.ToInt());    // 16777216  
}

测试代码中的荟萃类变量t1,t2别离界说为第15位和第16位,显示功效应该别离为32768和65536,t1功效32768是正确的,t2显示却为16777216,显然是错误的。

接下来,我用Delphi 2010写了雷同的测试代码:

type
  TTest = (tt0, tt15 = 15, tt16 = 16);  
  TTests = set of TTest;  
      
procedure TForm1.Button1Click(Sender: TObject);  
var
  t1, t2: TTests;  
begin
  t1 := [tt15];  
  t2 := [tt16];  
  ShowMessage(IntToStr(LongWord(t1)));  // 32768  
  ShowMessage(IntToStr(LongWord(t2)));  // 65536  
end;

而Delphi 2010代码显示功效完全正确。

很明明,C++Builder 2010代码中的荟萃类变量t2向左多移了8位,即16777216是第24位置位后的功效。

我调出C++Builder 2010荟萃类源代码文件sysset.h,查察了一下其ToInt函数,发明问题就出在这里,请看源码中数据界说和ToInt函数代码:

template<class T, unsigned char minEl, unsigned char maxEl>  
class RTL_DELPHIRETURN SetBase  
{  
protected:  
  unsigned char Data[((((int)(maxEl/8))-((int)(minEl/8))+1) != 3)?  
     (((int)(maxEl/8))-((int)(minEl/8))+1): 4];  
};  
      
template<class T, unsigned char minEl, unsigned char maxEl>  
class RTL_DELPHIRETURN Set : SetBase<T, minEl, maxEl>  
{  
      
  ......  
      
  int __fastcall ToInt(void) const
  {  
#pragma option push -w-inl  
  int Result = 0;  
  for (int i = sizeof(Data)-1; i >= 0; i--)  
  {  
    Result |= Data[i];  
    Result <<= (i * sizeof(unsigned char) * 8);  
  }  
  return Result;  
#pragma option pop  
  }  
      
  ......  
      
};

上面测试用的荟萃类TTests最小成员值=0,最大成员值=16,按源码数据长度界说公式计较得3,Byte范例的数组Data长度=4,测试代码中的荟萃类变量t1和t2的数据别离为"\0\x80\0\0"和"\0\0\1\0",在ToInt函数转换时,t1的有效起始下标i=1,Result赋值0x80后共左移了2次8位,功效为0x8000(32768);而t2的有效起始下标i=2,Result赋值1后左移了3次共24位(即2 * 1 * 8 = 16,1 * 1 * 8 = 8,0 * 1 * 8 = 0),功效为0x1000000(16777216)。

可以将源码中ToInt函数做如下修改:

  int __fastcall ToInt(void) const
  {  
#pragma option push -w-inl  
  int Result = 0;  
  for (int i = sizeof(Data)-1; i >= 0; i--)  
  {  
    Result |= Data[i];  
    if (i)  
        Result <<= (sizeof(unsigned char) * 8);  
  }  
  return Result;  
#pragma option pop  
  }

我只查察了C++Builder 2010,并且也只涉及ToInt函数,其它版本或函数有无问题不清楚,显然这个BUG在措施中有大概是致命的,望列位C++Builder措施员鉴戒。

作者:csdn博客 阿发伯

 

    关键字:

天才代写-代写联系方式