Long to char array - where is the bug?

 

Hi,

I need to store a long or ulong value into a char array. Therefore I split the value into pieces of 8 bit and store these parts into 8 elements of a char array. Following macro is used:

   #define L64_TO_UCHAR(value,array,pos) { array[pos+0]=uchar(value&0xFF);array[pos+1]=(uchar)((value>>8)&0xFF);array[pos+2]=(uchar)((value>>16)&0xFF);array[pos+3]=(uchar)((value>>24)&0xFF);array[pos+4]=(uchar)((value>>32)&0xFF);array[pos+5]=(uchar)((value>>40)&0xFF);array[pos+6]=(uchar)((value>>48)&0xFF);array[pos+7]=(uchar)((value>>56)&0xFF); }
   #define UCHAR_TO_L64(array,pos) (array[pos+7]<<56|array[pos+6]<<48|array[pos+5]<<40|array[pos+4]<<32|array[pos+3]<<24|array[pos+2]<<16|array[pos+1]<<8|array[pos])
   

For testing within OnInit(), this is used:

   
   uchar chars[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
   ulong l=0xFFFFFFFFFFFFFFFF;
   L64_TO_UCHAR(l,chars,0);
   l=UCHAR_TO_L64(chars,0);

Works with long and ulong.


But, when I use

   
   uchar chars[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
   ulong l=2906252937;
   L64_TO_UCHAR(l,chars,0);
   l=UCHAR_TO_L64(chars,0);
   

it doesn´t. The result-value of l is just a random number. 


What´s going wrong here?

   

 

Here are the serialize() and deserialize functions for MQL:

//+------------------------------------------------------------------+
//| Convert any value type to byte array                             |
//| Serialize MQL data -> byte array.                                |
//+------------------------------------------------------------------+
// like StringToCharArray() with support for any data type.

template<typename TValue>
void byte_cast(const TValue &value, uchar &byte_array[], int start = 0)
  {
   union _u
     {
      TValue      value;
      uchar       bytes[sizeof(TValue)];
     } u;

   u.value = value;
   ArrayCopy(byte_array, u.bytes, start);
  }
//+------------------------------------------------------------------+
//| Convert byte array to any value type                             |
//| De-serialize byte array -> MQL data.                             |
//+------------------------------------------------------------------+
template<typename TValue>
void deserialize(const uchar &byte_array[], TValue &value, int start = 0)
  {
   union _u
     {
      TValue      value;
      uchar       bytes[sizeof(TValue)];
     } u;

   ArrayCopy(u.bytes, byte_array, 0, start, sizeof(TValue));
   value = u.value;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
//-- Download quotes
   MqlRates rates[];
   int total = CopyRates(Symbol(), Period(), 0, 3, rates);
   ArrayPrint(rates);

//-- Convert them to a byte representation
   uchar byte_array[];
   ArrayResize(byte_array, total * sizeof(MqlRates));
   for(int i = 0, dst = 0; i < total; i++, dst += sizeof(MqlRates))
     {
      byte_cast(rates[i], byte_array, dst);
     }

//-- Display the byte representation
   ArrayPrint(byte_array);

//-- De-serialize the byte representation
   MqlRates rates2[];
   ArrayResize(rates2, ArraySize(byte_array) / sizeof(MqlRates));
   for(int start = 0, i = 0; start < ArraySize(byte_array); start += sizeof(MqlRates), i++)
     {
      deserialize(byte_array, rates2[i], start);
     }
   ArrayPrint(rates2);

//-- Compare the results
   Print("compare = ", ArrayCompare(rates, rates2));
  }
//+------------------------------------------------------------------+

/*
  test (GBPUSD,H1)                       [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
  test (GBPUSD,H1)      [0] 2021.06.23 12:00:00 1.39697 1.39709 1.39534 1.39599          3771        0             0
  test (GBPUSD,H1)      [1] 2021.06.23 13:00:00 1.39599 1.39720 1.39552 1.39663          4073        0             0
  test (GBPUSD,H1)      [2] 2021.06.23 14:00:00 1.39662 1.39704 1.39540 1.39665          2734        0             0

  test (GBPUSD,H1)      [  0]  64  34 211  96   0   0   0   0 210 227 247  54 253  89 246  63  38  25  57  11 123  90 246  63 108 207  44   9  80  83 246  63  75 176  56 156
  test (GBPUSD,H1)      [ 36] 249  85 246  63 187  14   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  80  48 211  96   0   0   0   0  75 176  56 156
  test (GBPUSD,H1)      [ 72] 249  85 246  63   9 138  31  99 238  90 246  63 106 159 142 199  12  84 246  63 184 204 233 178 152  88 246  63 233  15   0   0   0   0   0   0
  test (GBPUSD,H1)      [108]   0   0   0   0   0   0   0   0   0   0   0   0  96  62 211  96   0   0   0   0  70   8 143  54 142  88 246  63 238  66 115 157  70  90 246  63
  test (GBPUSD,H1)      [144]  22 106  77 243 142  83 246  63 155  85 159 171 173  88 246  63 174  10   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

  test (GBPUSD,H1)                       [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
  test (GBPUSD,H1)      [0] 2021.06.23 12:00:00 1.39697 1.39709 1.39534 1.39599          3771        0             0
  test (GBPUSD,H1)      [1] 2021.06.23 13:00:00 1.39599 1.39720 1.39552 1.39663          4073        0             0
  test (GBPUSD,H1)      [2] 2021.06.23 14:00:00 1.39662 1.39704 1.39540 1.39665          2734        0             0

  test (GBPUSD,H1)      compare = 0
*/
 
amrali:

Here are the serialize() and deserialize functions for MQL:

Thank you, already though about union as well, interesting solution!

 

Original solved by change of casting:

#define UCHAR_TO_L64(array,pos) (ulong(array[pos+7])<<56|ulong(array[pos+6])<<48|ulong(array[pos+5])<<40|ulong(array[pos+4])<<32|ulong(array[pos+3])<<24|ulong(array[pos+2])<<16|ulong(array[pos+1])<<8|ulong(array[pos]))
 
Doerk Hilger:

Original solved by change of casting:

Good solution 
Reason: