"long" variable overflowing like an "int"

Hi everyone,

I have a sketch which I'm running on an Arduino Mega 2560.

In this sketch I declare two volatile long int variables that are used for tracking encoder pulses (with interrupts) from two motors (x and y).

The problem is that when displaying these on the serial monitor, I find that they overflow at +32,767 or -32,768, as I'd expect integers to do.

I've tried changing long int to long but to no avail.

Here are the relevant pieces of code:

volatile long int x_position = 0; //Global coordinates, remembering last position
volatile long int y_position = 0;

const int CONVERSION = 1000; //Convertion between ecnoder pulses (as depicted in x_position and y_position) and mm

void displayCoordinates(int x_position, int y_position)
{
  Serial.print("(x,y) in pulses:(");
  Serial.print(x_position);
  Serial.print(",");
  Serial.print(y_position);
  Serial.print(")");
  Serial.print("(x,y) in mm:("); //For CONVERSION pulses per mm
  Serial.print(x_position/CONVERSION);
  Serial.print(",");
  Serial.print(y_position/CONVERSION);
  Serial.print(")");
  Serial.println();
}

Hope that's specific enough. If you need more details please let me know.

Thanks a lot! :astonished:

Gadi.

void displayCoordinates(int x_position, int y_position)

If you are passing longs to this, I'm not surprised you're having problems.

dxw00d:

void displayCoordinates(int x_position, int y_position)

If you are passing longs to this, I'm not surprised you're having problems.

Now isn't this embarrassing.. :blush:

Thanks!

Now isn't this embarrassing..

No, it is a well known fact that you are nearly "blind" when it comes to reading your own code (or any other document). Your brain just makes the same mistake over and over again. A trick that helps is reading code (or your doc) backwards, yes it takes much time but you are very aware of what you read.

No, don't feel bad about it, especially if you program on architectures where an 'int' is 32 bits wide at the same time as programming for Arduino.

Got the same problem. But my code is so simple, I don't think I'm converting it at any way to an int.
When I put the time to 40000, I get an output of -25536.
Any helps would be great.

long myTime = 0;

void setup(){
  Serial.begin(57600);
  myTime = 40*1000;
}

void loop(){
  Serial.println(myTime);
  delay(2000);
}

For integer math (more specifically 'int' math) 40000 = -25536. It is the difference between a signed typed and an unsigned type.

Unless told otherwise, the compiler will assume the int type for literal values. You need to tell it to use long type instead:

myTime = 40L*1000L;

Note the L at the end to specify Long. UL can be used to specify Unsigned Long.

1 Like

Ok, thanks.
But why do I declare it as long (or unsigned long, both didn't work) if he still works with it like an integer.
Get it that he does, but is there any higher philosophy?

Kalbshack:
Ok, thanks.
But why do I declare it as long (or unsigned long, both didn't work) if he still works with it like an integer.
Get it that he does, but is there any higher philosophy?

The intermediate match is assumed to be an int, you're just assigning it to a long.

If you're working with the long variable, it treats it as a long.

Kalbshack:
Ok, thanks.
But why do I declare it as long (or unsigned long, both didn't work) if he still works with it like an integer.
Get it that he does, but is there any higher philosophy?

Yes, without at least one suffix (U, L, and LL, or the lower case varients u, l, and ll -- but you really don't want to use 'l' since humans likely confuse it with the digit '1'), the compiler gives it a type based on the value:

  • If the value is between INT_MIN and INT_MAX inclusive, the type is signed int
  • If the value is between INT_MAX+1 and UINT_MAX inclusive, the type is unsigned int
  • If the value is between LONG_MIN and INT_MIN-1 or UINT_MAX+1 and LONG_MAX, the type is signed long
  • If the value is between LONG_MAX+1 and ULONG_MAX, the type is unsigned long
  • If the value is between LLONG_MIN and LONG_MIN-1 or ULONG_MAX+1 and LLONG_MAX, the type is signed long long
  • If the value is between LLONG_MAX+1 and ULLONG_MAX, the type is unsigned long long
  • If the value cannot be represented as a signed long long or unsigned long long value, it is an error

Since both 40 and 1000 are greater than or equal to -32768 (INT_MIN) and less than or equal to 32767 (INT_MAX), the types are signed int. If you had written 40000, then the type would have been unsigned int.

In the ISO C world, this is called value preserving, and it is one of the changes that the original C standards committee did over the original K&R C language, which was somewhat looser, and would go from signed int to signed long without going to unsigned int (called sign preserving).