Is it a bug about the data type of -2147483649 ?

 

I found the literal value -2147483649 and 2147483648 are hard-coded as uint type ,I think they should be long type.

Test code:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
//---
   //INT_MIN = -2147483648, INT_MAX =  2147483647

   Print("sizeof(2147483648)  = ",sizeof(2147483648));  //4 bytes,expected to be long type
   Print("sizeof(-2147483649) = ",sizeof(-2147483649)); //4 bytes,expected to be long type

   Multiply(-2147483649,2147483648);   
   
   Print("-2147483649 = ",-2147483649);
   Test(-2147483649);  

}
//+------------------------------------------------------------------+
template<typename T1,typename T2>
void Multiply(T1 a,T2 b)
{
   printf("");
   Print(__FUNCSIG__);
   printf("a type = %s, b type = %s",typename(a),typename(b));
   Print("a = ",a,", b = ",b);  
   printf(""); 
}
//+------------------------------------------------------------------+
void Test(long a)
{
   printf("a type = %s",typename(a));
   printf("a = %I64d",a);
}
//+------------------------------------------------------------------+

Test result:

Verion 5.0 Build 3391

Edited, please note:

  -2147483649 = INT_MIN - 1

  2147483648  = INT_MAX +1

What I tesed is  -2147483649 instead of INT_MIN.

 

Test on MT4, version 4.0 build 1353

the result shows:

-2147483649 is hard-coded as long type and 2147483648 is uint type.

 

"long" is 8 bytes, not 4 bytes. and those values are of "int" type which is 4 bytes. Please refer to the documentation:

Documentation on MQL5: Language Basics / Data Types / Integer Types

int

4

- 2 147 483 648

2 147 483 647

int

long

8

-9 223 372 036 854 775 808

9 223 372 036 854 775 807

__int64

Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Numerical Type Constants

INT_MIN

Minimal value, which can be represented by int type

-2147483648

INT_MAX

Maximal value, which can be represented by int type

2147483647

 
Fernando Carreiro #:

"long" is 8 bytes, not 4 bytes. and those values are of "int" type which is 4 bytes. Please refer to the documentation:

Thanks. I know that well.

The bug is the literal value  -2147483649 should be coded as long type instead of uint.

The tested result on mt4 shows it is long type (8 bytes)

 
Ziheng Zhuang #:Thanks. I know that well.The bug is the literal value  -2147483649 should be coded as long type instead of uint. The tested result on mt4 shows it is long type (8 bytes)

How can a negative constant be typed as a "uint"? And why should it be typed as a "long"? Your code is faulty. see the following ...

void OnStart()
{
   Print( "INT_MAX: ", INT_MAX, ", sizeof = ", sizeof(INT_MAX), ", type = ", typename(INT_MAX) );
   Print( "INT_MIN: ", INT_MIN, ", sizeof = ", sizeof(INT_MIN), ", type = ", typename(INT_MIN) );
};
// Results the same on both MT4 and MT5
INT_MAX: 2147483647, sizeof = 4, type = int
INT_MIN: -2147483648, sizeof = 4, type = int
 
Fernando Carreiro #:

How can a negative constant be typed as a "uint"? And why should it be typed as a "long"? Your code is faulty. see the following ...

You did not notice that -2147483649 is INT_MIN -1 , so  -2147483649  is not in the range of int type

-2147483649  should be hard-coded as long type but the mt5 compiler coded it as uint type 

 

Edited, please note:

  -2147483649 = INT_MIN - 1

  2147483648  = INT_MAX +1

What I tesed is  -2147483649 instead of INT_MIN.

 
Ziheng Zhuang #: You did not notice that -2147483649 is INT_MIN -1 , so  -2147483649  is not in the range of int type -2147483649  should be hard-coded as long type but the mt5 compiler coded it as uint type 

Ok, now I understand. I did not notice that your values were off by one. Sorry about the misunderstanding.

Yes, you are correct. The compiler is incorrectly considering the value as an "unit" and wrapping the value.

This does seem to be a bug present in both MT4 and MT5.

void OnStart()
{
   Print( "INT_MAX: ", INT_MAX, ", sizeof = ", sizeof(INT_MAX), ", type = ", typename(INT_MAX) );
   Print( "INT_MIN: ", INT_MIN, ", sizeof = ", sizeof(INT_MIN), ", type = ", typename(INT_MIN) );
   Print( "2147483648: ", 2147483648, ", sizeof = ", sizeof(2147483648), ", type = ", typename(2147483648) );
   Print( "-2147483649: ", -2147483649, ", sizeof = ", sizeof(-2147483649), ", type = ", typename(-2147483649) );
   Print( "2147483649: ", 2147483649, ", sizeof = ", sizeof(2147483649), ", type = ", typename(2147483649) );
   Print( "-2147483650: ", -2147483650, ", sizeof = ", sizeof(-2147483650), ", type = ", typename(-2147483650) );
};
INT_MAX: 2147483647, sizeof = 4, type = int
INT_MIN: -2147483648, sizeof = 4, type = int
2147483648: 2147483648, sizeof = 4, type = uint
-2147483649: 2147483647, sizeof = 4, type = uint
2147483649: 2147483649, sizeof = 4, type = uint
-2147483650: 2147483646, sizeof = 4, type = uint

 

My work-around was to use "(long)INT_MIN - 1" and "(long)INT_MAX + 1".

void OnStart()
{
   Print( "INT_MAX: ", INT_MAX, ", sizeof = ", sizeof(INT_MAX), ", type = ", typename(INT_MAX) );
   Print( "INT_MIN: ", INT_MIN, ", sizeof = ", sizeof(INT_MIN), ", type = ", typename(INT_MIN) );
   Print( "2147483648: ", 2147483648, ", sizeof = ", sizeof(2147483648), ", type = ", typename(2147483648) );
   Print( "-2147483649: ", -2147483649, ", sizeof = ", sizeof(-2147483649), ", type = ", typename(-2147483649) );
   Print( "2147483649: ", 2147483649, ", sizeof = ", sizeof(2147483649), ", type = ", typename(2147483649) );
   Print( "-2147483650: ", -2147483650, ", sizeof = ", sizeof(-2147483650), ", type = ", typename(-2147483650) );
   Print( "INT_MAX + 1: ", (long)INT_MAX + 1, ", sizeof = ", sizeof((long)INT_MAX + 1), ", type = ", typename((long)INT_MAX + 1) );
   Print( "INT_MIN - 1: ", (long)INT_MIN - 1, ", sizeof = ", sizeof((long)INT_MIN - 1), ", type = ", typename((long)INT_MIN - 1) );
};
INT_MAX: 2147483647, sizeof = 4, type = int
INT_MIN: -2147483648, sizeof = 4, type = int
2147483648: 2147483648, sizeof = 4, type = uint
-2147483649: 2147483647, sizeof = 4, type = uint
2147483649: 2147483649, sizeof = 4, type = uint
-2147483650: 2147483646, sizeof = 4, type = uint
INT_MAX + 1: 2147483648, sizeof = 8, type = long
INT_MIN - 1: -2147483649, sizeof = 8, type = long
 

Another work-around is to insert "(long)" after the sign, (e.g. "-(long)2147483650").

void OnStart()
{
   Print( "INT_MAX: ", INT_MAX, ", sizeof = ", sizeof(INT_MAX), ", type = ", typename(INT_MAX) );
   Print( "INT_MIN: ", INT_MIN, ", sizeof = ", sizeof(INT_MIN), ", type = ", typename(INT_MIN) );
   Print( "2147483648: ", 2147483648, ", sizeof = ", sizeof(2147483648), ", type = ", typename(2147483648) );
   Print( "-2147483649: ", -2147483649, ", sizeof = ", sizeof(-2147483649), ", type = ", typename(-2147483649) );
   Print( "2147483649: ", 2147483649, ", sizeof = ", sizeof(2147483649), ", type = ", typename(2147483649) );
   Print( "-2147483650: ", -2147483650, ", sizeof = ", sizeof(-2147483650), ", type = ", typename(-2147483650) );
   Print( "(long)INT_MAX + 1: ", (long)INT_MAX + 1, ", sizeof = ", sizeof((long)INT_MAX + 1), ", type = ", typename((long)INT_MAX + 1) );
   Print( "(long)INT_MIN - 1: ", (long)INT_MIN - 1, ", sizeof = ", sizeof((long)INT_MIN - 1), ", type = ", typename((long)INT_MIN - 1) );
   Print( "-(long)2147483650: ", -(long)2147483650, ", sizeof = ", sizeof(-(long)2147483650), ", type = ", typename(-(long)2147483650) );
};
INT_MIN: -2147483648, sizeof = 4, type = int
2147483648: 2147483648, sizeof = 4, type = uint
-2147483649: 2147483647, sizeof = 4, type = uint
2147483649: 2147483649, sizeof = 4, type = uint
-2147483650: 2147483646, sizeof = 4, type = uint
(long)INT_MAX + 1: 2147483648, sizeof = 8, type = long
(long)INT_MIN - 1: -2147483649, sizeof = 8, type = long
-(long)2147483650: -2147483650, sizeof = 8, type = long
 
Fernando Carreiro #:

Another work-around is to insert "(long)" after the sign, (e.g. "-(long)2147483650").

Thank you. This is very interesting work-around I never know.

Reason: