Author Topic: unsigned long problem [SOLVED]  (Read 2786 times)

0 Members and 1 Guest are viewing this topic.

Offline RajTopic starter

  • Frequent Contributor
  • **
  • Posts: 694
  • Country: in
  • Self taught, experimenter, noob(ish)
unsigned long problem [SOLVED]
« on: September 21, 2017, 04:58:17 pm »
i've been  |O (banging my head against the wall) trying to debug my arduino (yeah,go on, call me a noob)

when I type-
unsigned long     reading = 0;
reading =0+ (0xFF00>> 8 );
Serial.print(reading);

I get 255, as expected


when i type
unsigned long     reading = 0xFF00;
Serial.print(reading);

I get 65280


but when I type
unsigned long     reading = 0;
reading =0+ (0xFF<< 8 );
Serial.print(reading);

I get 4294967040 instead of 65280
:-BROKE :scared:


try it- if you run this-
void setup() {
 Serial.begin(9600);   
unsigned long     reading = 0;
reading =0+ (0xFF00>> 8 );
Serial.println(reading);
reading = 0xFF00;
Serial.println(reading);
reading =0+ (0xFF<< 8 );
Serial.println(reading);
Serial.println("blah");
}


you get
255
65280
4294967040
blah



instead of
255
65280
65280
« Last Edit: September 21, 2017, 06:05:06 pm by Raj »
 

Online Andy Watson

  • Super Contributor
  • ***
  • Posts: 2085
Re: unsigned long problem
« Reply #1 on: September 21, 2017, 05:10:44 pm »
It is treating the 0xFF as a signed value (probably defaulting to signed integer). The left shift causes it to be signed extended to FFFFFF00. You need to cast the original FF as unsigned int.

 

Online IanB

  • Super Contributor
  • ***
  • Posts: 11884
  • Country: us
Re: unsigned long problem
« Reply #2 on: September 21, 2017, 05:12:53 pm »
It's caused by promotion rules. When you write the 8-bit constant 0xFF while you are doing 32-bit arithmetic the compiler is promoting it to a 32-bit constant 0xFFFFFFFF, which is 2^32. When you now shift this left by 8 bits, you get 0xFFFFFF00, which is 42494967040 in decimal.

I don't know why your 16-bit constants like 0xFF00 didn't get promoted similarly. I would have to do a lot of reading of documentation to find that out.

If you are doing arithmetic with unsigned long (32 bits), then make sure you write all your constants as 32-bit constants. Write 0x000000FF rather than 0xFF.

« Last Edit: September 21, 2017, 05:14:53 pm by IanB »
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: unsigned long problem
« Reply #3 on: September 21, 2017, 05:15:16 pm »
Try 0xFFu
 

Offline RajTopic starter

  • Frequent Contributor
  • **
  • Posts: 694
  • Country: in
  • Self taught, experimenter, noob(ish)
Re: unsigned long problem
« Reply #4 on: September 21, 2017, 05:22:18 pm »
Ah, finally got it to work bu by changing unsigned long to unsigned int
now
reading = 0xFF;
reading= reading*256;
Serial.println(reading);


gives me 65280
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12858
Re: unsigned long problem
« Reply #5 on: September 21, 2017, 05:30:44 pm »
C defaults to signed integer maths unless you tell it otherwise.  Officially it doesn't 'snoop' across the equals sign to see what you are doing with the result*.  C integer promotion rules are a bit tricky and there is no substitute for studying the standard or K&R.  Also see http://c-faq.com/expr/preservingrules.html

0xFF is 255, an integer, its small enough to fit in a singed integer so that's what it is taken as.   <<8 causes an overflow, its now -256.  If you enter it as 0xFF00, the same bit pattern, its too large to fit in a signed integer so the compiler uses a signed long.   When the signed integer -256 is assigned to a long, its sign extended so its still -256.  -256 in a long is the same bit pattern as 0xFFFFFF00, and if you dump that into an unsigned long you get 4294967040.

To avoid problems, you need to force the calculation to use a type compatible with the target size and type.  The easiest would be:
Code: [Select]
unsigned long     reading = 0;
reading =0+ (0xFFUL<< 8 );
Serial.print(reading);
Note the 'UL' suffix on the value being shifted - that tells the compiler its an unsigned long, so in this calculation it never overflows and cant be sign extended.
 
* smarter compilers skip calculating high bytes that will be lost to truncation, but the final result must be identical to performing the full calculation.
 
The following users thanked this post: Raj


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf