Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird results from multiplying uint16_t variable with a number

Tags:

c

I have a very simple piece of C code that gives me weird result. I'm developing a simple wireless sensor network application for Micaz motes. It seems to have ATmega128L 8 bit AVR microprocessors. I'm using AVR studio to write and compile the code.

uint16_t myvariable;
uint16_t myresult;
myresult = myvariable*256;

When myvariable is 3, I found myresult was always reset to 512. Just wondering why it works like this. My guess is, the mixture of such a literal number 256 and uint16_t magically causes the problem. But I don't know why. Could anybody give a detailed explanation on this? Appreciate for any help!

More detailed source code is as follows.

static uint16_t myvariable[2];
static uint8_t AckMsg[32];
uint16_t myresult[MAX_SENDERS];

void protocol()  
{           
    if(thisnodeid != 5){   // sender nodes
      while (1)
      {         
        if(AckReceived && !MsgSent) {
          // If ACK received and a new message not sent yet,
          // send a new message on sending node.
        }

        else if(!AckReceived && MsgSent)
        {
            lib_radio_receive_timed(16, 32, AckMsg, 120);
            myvariable[0] = AckMsg[0];
            myvariable[1] = AckMsg[1];
            // Bug!!!, variable overflowed.
            myresult[thisnodeid] = 256*myvariable[1] + myvariable[0];  
        }

      }
    }           

}

What I really want to figure out is, how the compiler compiles following line of code, because I know it's this line of code causes the bug. Thanks in advance for any information!

myresult[thisnodeid] = 256*myvariable[1] + myvariable[0]; 

When myvariable[1]=3, myvariable[0]=0, I always get myresult[] = 512. Looks 768 is always reset to 512. Just don't know why.

like image 522
kevinlu Avatar asked Nov 13 '22 07:11

kevinlu


1 Answers

I tried this code without any problem on a standard system:

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define MAX_SENDERS 10
static uint16_t myvariable[2];
static uint8_t AckMsg[32];
uint16_t myresult[MAX_SENDERS];
main()
{
    AckMsg[0] = 0;
    AckMsg[1] = 3;
    myvariable[0] = AckMsg[0];
    myvariable[1] = AckMsg[1];
    myresult[0] = 256*myvariable[1] + myvariable[0];  
    printf("%d", (int)myresult[0]);
}

So to debug you code, you should try to replace the lines :

myvariable[0] = AckMsg[0];
myvariable[1] = AckMsg[1];
// Bug!!!, variable overflowed.
myresult[thisnodeid] = 256*myvariable[1] + myvariable[0]; 

by :

uint16_t tmp;
myvariable[0] = AckMsg[0];
myvariable[1] = AckMsg[1];
tmp = 256*myvariable[1] + myvariable[0]; 
myresult[thisnodeid] = 256*myvariable[1] + myvariable[0]; 
printf("%d %d\n", (int)(AckMsg[0]), (int)(AckMsg[1]));
printf("%d %d\n", (int)(thisnodeid), (int)(MAX_SENDERS));
printf("%d %d\n", (int)(myvariable[0]), (int)(myvariable[1]));
printf("%d %d\n", (int)(tmp), (int)(myresult[thisnodeid]));

This may bring useful information on the origin of the problem.

If you cannot print something in you debugger, you can try the following thing:

uint16_t i = 0;
uint16_t n = 255;
myresult[thisnodeid] += myvariable[1];
while (i != n) {
    myresult[thisnodeid] += myvariable[1];
    i += 1;
}
myresult[thisnodeid] += myvariable[0]; 

It will be slow but it may allow you to detect where the overlow is actually happening, because the only variable that will be greater than 255 is myresult.

like image 123
Vincent Avatar answered Dec 07 '22 12:12

Vincent