unsigned int issue

Ok i’m having a bit of a delema and I’m hoping someone can give me some insight into my issue. I don’t see a need to have my variable TcpMesageLengthCheck as a glabal but if I delare it inside of my funciton ParseMessage() it gives me the wrong value. If I declare the variable unsigned int TcpMesageLengthCheck globally the code works. If i declare it locally to a function it does not work. The way that doesn’t work returns the value of 10 as the unsigned int. The way that works returns 6666 like it should. I’ve posted both ways below. Any insite would be great! IS it an error in the compiler or is it my error?

This way doesn’t work!

unsigned int messageLengthCounter = 6666;
unsigned int testvalue;

byte wirelessMessage[] = {0x44, 0x00, 0x00, 0x1A, 0x0A, 0x01};


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(13,OUTPUT);
}

void loop() 
{

  testvalue = ParseMessage();
  Serial.print("Test Value: ");
  Serial.println(testvalue);
  delay(10000);
}



int ParseMessage()
{

  unsigned int TcpMesageLengthCheck = (wirelessMessage[4]) + (wirelessMessage[3] >> 8) + (wirelessMessage[2] >> 16) + (wirelessMessage[1] >> 24);
  unsigned int messageNumber = wirelessMessage[5];
  
  if(wirelessMessage[0] == 'D')
  {
    if(TcpMesageLengthCheck == messageLengthCounter)
    {
      Serial.print("Message Number : ");
      Serial.println(messageNumber);
      Serial.println(" ");
      Serial.println(" ");
    }
    else
    {
      Serial.println("Incomplete message receiced");
      Serial.print("TCP Message Length Check : ");
      Serial.println(TcpMesageLengthCheck);
      Serial.print("Message Number : ");
      Serial.println(messageNumber);
      Serial.println(" ");
      Serial.println(" ");
    }
  }
  else
  {
    Serial.println("NOT THE RIGHT MESSAGE TYPE");   
  }
  return TcpMesageLengthCheck;
}

This way Works

unsigned int messageLengthCounter = 6666;
unsigned int testvalue;
unsigned int TcpMesageLengthCheck;

byte wirelessMessage[] = {0x44, 0x00, 0x00, 0x1A, 0x0A, 0x01};


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(13,OUTPUT);
}

void loop() 
{

  testvalue = ParseMessage();
  Serial.print("Test Value: ");
  Serial.println(testvalue);
  delay(10000);
}



int ParseMessage()
{

  TcpMesageLengthCheck = (wirelessMessage[4]) + (wirelessMessage[3] >> 8) + (wirelessMessage[2] >> 16) + (wirelessMessage[1] >> 24);
  unsigned int messageNumber = wirelessMessage[5];
  
  if(wirelessMessage[0] == 'D')
  {
    if(TcpMesageLengthCheck == messageLengthCounter)
    {
      Serial.print("Message Number : ");
      Serial.println(messageNumber);
      Serial.println(" ");
      Serial.println(" ");
    }
    else
    {
      Serial.println("Incomplete message receiced");
      Serial.print("TCP Message Length Check : ");
      Serial.println(TcpMesageLengthCheck);
      Serial.print("Message Number : ");
      Serial.println(messageNumber);
      Serial.println(" ");
      Serial.println(" ");
    }
  }
  else
  {
    Serial.println("NOT THE RIGHT MESSAGE TYPE");   
  }
  return TcpMesageLengthCheck;
}

What happens when you shift a byte 8 places? What kind of register is used to hold the value? How about 16 places? 24? The registers are int registers, unless you use a cast, which will not result in the values that you think you'll get. So, I can't see how either of your codes will work, for any definition of work that I understand.

I don't see how shifting a byte 24 places is going to result in something that will fit in an int, even if you use an appropriate cast. So, again, I can't see how either of your codes will work, for any definition of work that I understand.

Paul even with an int Cast it doesn't work. when I declare the variable locally but it does when I declare it globally. I think it's a bug in the compiler to be honest.

unsigned int TcpMesageLengthCheck = ((int)wirelessMessage[4]) + ((int)wirelessMessage[3] >> 8) + ((int)wirelessMessage[2] >> 16) + ((int)wirelessMessage[1] >> 24);

Paul even with an int Cast it doesn't work.

Because you need to be using unsigned long, not int. An int is 16 bits. Unless you have a Due, in which case you are in the wrong place.

Hi there

TcpMesageLengthCheck = (wirelessMessage[4]) + (wirelessMessage[3] >> 8) + (wirelessMessage[2] >> 16) + (wirelessMessage[1] >> 24);

Are bytes 1 through 4 of the array meant to form a 32 bit unsigned message length? With byte 1 being the MSB and byte 4 the LSB?

If so, then I think you should be left shifting the byte values by 8, 16 and 24 bits (i.e. multiplying by 2^8, 2^16 and 2^24), and then summing the results (with suitable attention to type casts).

EDIT: With your test data {0x44, 0x00, 0x00, 0x1A, 0x0A, 0x01}, this would indeed give decimal 6666 as the length.

Regards

Ray

... and not trying to stuff them into a sixteen bit variableunsigned int TcpMesageLengthCheck; (unless you're on a Due)

Can no one explain why this is working as a global not a local variable though? I understand the syntax error but that isn’t my question.

I know this is proper syntax and it works like a charm but I found out the issue in question purely by accident and that is more what my question is based on. Why does it work with a global and not with a local variable. That is really the only question. According to C structure this way is the proper way to do what I’m trying to do for an 8bit system and it works like a charm no matter where the variable TcpMessageLengthCheck() is declared.

int ParseMessage()
{

  unsigned int TcpMesageLengthCheck = ((int)wirelessMessage[1] << 24) | ((int)wirelessMessage[2] << 16) | ((int)wirelessMessage[3] << 8) | ((int)wirelessMessage[4]);
  unsigned int messageNumber = wirelessMessage[5];
  
  Serial.print("Message Length Counter: ");
  Serial.println(messageLengthCounter);
  Serial.print("TCP Message Length Check: ");
  Serial.println(TcpMesageLengthCheck);
      
  if(wirelessMessage[0] == 'D')
  {
    if(TcpMesageLengthCheck == messageLengthCounter)
    {
      
      Serial.print("Message Number: ");
      Serial.println(messageNumber);
      Serial.println(" ");
      Serial.println(" ");
    }
    else
    {
      Serial.println("Incomplete message receiced");
      Serial.println(" ");
      Serial.println(" ");
    }
  }
  else
  {
    Serial.println("NOT THE RIGHT MESSAGE TYPE");   
  }
  return TcpMesageLengthCheck;
}
unsigned int TcpMesageLengthCheck = ((int)wirelessMessage[1] << 24) | ((int)wirelessMessage[2] << 16) | ((int)wirelessMessage[3] << 8) | ((int)wirelessMessage[4]);

Can you please just tell us which board you’re running this on?
It’s terribly important.

actually the board i"m running it on is not terrible important. I'm running it on an arduino Uno though. IT does work properly when I run the last code I posted no matter where I place the variable though.

We're very mixed-up, aren't we? The Uno has sixteen bit "int"s.

That's why it was important.

I think were getting off topic here though. Why does it work when the unsigned int is declared globally and not locally? Are global variables different size then locally?

I think were getting off topic here though

Really? You think so?

Does it "work"? Perhaps you're only ever considering sixteen bit values.

No, variables do not have different size depending on where they are declared.

What happened to the rest of the assertions in reply #8?

You are correct i'm only basic this on 16bit unsigned ints of 65535. I know it blows up on anything larger. I understand that I should be using an unsigned long to convert FF FF FF FF to 4294967295. I do know that parts of the code have holes in them but for unsigned ints of 65535 that code works for a global unsigned int but not a local unsigned it. My point is it shouldn't work either way!

I've just tried both the original programs posted on a Uno.

They both give "incomplete message received" and a length of 10.

My apologies. I was fixing my reply in 8 as you typed your reply I saw the error there and wanted to correct it.

the http://arduino.cc/en/Reference/int does state 16bit for anything but the due and 32 bit for the due. I am used to working in the 32 bit world and I do understand that was a mess up on my part to use a 32 bit int for a 16 bit int container. Still curious as why it doesn't blow up completely with a global variable like it does for a local.

I just tried it on a different machine and it failed both times too. so here is where it gets really confusing. Running ubuntu 12.04 64-bit and Arduino 1.0 it works when i declare it globally and not locally.

When i run it on Arduino 1.0.5 on widows7 pro 64it blows up and i get 10 both ways. So either it's my machine doing something differntly or something different in the linux compiler then the windows.

I want to see it fail no matter where the declaration of the variable is for the record.

To get a result of 6666, a [u]possible[/u] explanation is as follows.

Consider byte 3 (0x1A) of your test data, which the original code shifted right 8 places.

Since the variable that the sum will be assigned to is a 16-bit int, take the byte and cast to 16 bit.

Shift the 16 bit value right 8 places BUT circle those bits into the top byte of the 16 bits (instead of dropping them).

This would have the effect of shifting left by 8 places.

Then adding shifted byte 3 to byte 4 gives 6666. Other two bytes of the length are 0 so no impact on the result.

For anyone interested I found the answer I was looking for. When writing the variable locally to a function the variable is written to the stack and is overrunning part of the stack. When I declare the variable globally it is written to a different part of the stack and happens to be over written a different area of memory that is not pertained to my program.

When I declare the variable globally it is written to a different part of the stack

No, it isn't written to the stack at all.