Today, using C + + Builder 2010 to write a small code, use the collection class, can set the results of the operation is not correct, excluding other reasons, the final determination should be the collection class source code problem, the following is a collection of class test code:
Enum Ttest{tt0, tt15 =, tt16 =};
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
}
The collection class variable t1,t2 in the test code is defined as the 15th and 16th digits respectively, the result should be 32768 and 65536,t1 result 32768 is correct, T2 display is 16777216, obviously wrong.
Next, I wrote a similar test code with Delphi 2010:
Type
TTest = (tt0, tt15 =, tt16 =);
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
;
The Delphi 2010 code shows that the results are completely correct.
Obviously, the collection class variable in the C++builder 2010 code T2 moved 8 bits to the Zodo, that is, 16777216 is the result of the 24th bit position.
I pulled out the C++builder 2010 Collection Class source code file Sysset.h, looked at its toint function, found that the problem is here, please see the source code data definition and ToInt function codes:
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, MA xel>
{
...
.. 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
} ...
};
More Wonderful content: http://www.bianceng.cnhttp://www.bianceng.cn/Programming/cplus/
The above test set class Ttests minimum member value = 0, the maximum member value = 16, according to the source code data length definition formula calculated 3,byte type of array data length = 4, test code in the collection class variable T1 and T2 data are "\0\x80\0\0" and "\0\0\1\0 ", when the ToInt function is converted, T1 the effective starting subscript I=1,result after the assignment 0x80 the total left 2 times 8 digits, the result is 0x8000 (32768), and T2 effective starting subscript I=2,result assignment 1 after the left 3 times total 24 (that is 2 * 1 * 8 = 16,1 * 1 * 8 = 8,0 * 1 * 8 = 0), the result is 0x1000000 (16777216).
The ToInt function in the source code can be modified as follows:
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
}
I only looked at C++builder 2010, and also only involved in the ToInt function, other versions or functions are not clear, it is obvious that the bug in the program may be fatal, I hope you c++builder programmers vigilant.
Author: csdn Blog Alfaber