short to char
Since I didn't know about the Javelin's memory management(or lack thereof), I began writing my own class to deal with it. One requirement I have is to be able to create two char variables from a short. Please refer to the code below:
short nextPointer = 194;
short work = nextPointer;
work = (short)(work >> 8);
char a = (char)work;
char b = (char)(nextPointer - (256 * work));
The idea is that "work" will be shifted right 8 bits to remove the least significant bits. "work" now equals 0x0000, and "a" becomes 0x00. However, if I work out the expression on the last line, it comes out to 194 short, which is correct. When I copy this into char "b", b becomes 0xFFC2, when I really want 0x00C2.
Now.. I'm all sorts of confused, since I thought char was a 1-byte unsigned type, I'm not sure how this 0xFF00 fits in there. The result gives me -62.
Anyway, it seems the issue is that I cannot convert a short that is above 127 to a char, presumably because of converting between a signed and unsigned type. Can anybody help me out here? It seems like it should be a simple thing.
Thanks,
Dan
short nextPointer = 194;
short work = nextPointer;
work = (short)(work >> 8);
char a = (char)work;
char b = (char)(nextPointer - (256 * work));
The idea is that "work" will be shifted right 8 bits to remove the least significant bits. "work" now equals 0x0000, and "a" becomes 0x00. However, if I work out the expression on the last line, it comes out to 194 short, which is correct. When I copy this into char "b", b becomes 0xFFC2, when I really want 0x00C2.
Now.. I'm all sorts of confused, since I thought char was a 1-byte unsigned type, I'm not sure how this 0xFF00 fits in there. The result gives me -62.
Anyway, it seems the issue is that I cannot convert a short that is above 127 to a char, presumably because of converting between a signed and unsigned type. Can anybody help me out here? It seems like it should be a simple thing.
Thanks,
Dan
Comments
char b = 128; // b = 128 (0x80)
char a = 127; // a = 127 (0x7F)
a++; // a = 65408 (0xFF80)
This is killing me! Help!
Dan
Arrays of boolean,byte,char have 1 byte elements and 4 bytes overhead.
Arrays of short,int,reference have 2 byte elements and 4 bytes overhead.
Strings and StringBuffers are really arrays of char (in terms of storage).
Usually you don't use short except when assigning unsigned values >= 0x8000,
eg. int value = (short)0x89AF;
Note that short and int are both 16bits.
Promoting chars to int is done sign extended.
If you don't want that AND with 0xFF
char c = 0x89;
int value = c & 0xFF;
regards peter
Well one thing I noticed is that all expressions evaluate to int. I still cannot attain what I want. Just reading the manual, it didn't appear that int and short were any different. Both 16-bit signed numbers.
For my memory management class, I used short instead of int to differentiate between a regular number and what I consider a "pointer". I only need two basic functions:
Convert a short into two char variables, one representing the upper portion, the other representing the lower portion.
-and-
Convert two char variables (representing upper and lower) back into that same short value.
So I cannot convert 384(short) into two chars, and try to convert those two chars back to 384(short). It just doesn't work. I even tried to trim the upper portion by bitwise AND with 0xFF. I'm about ready to just find another chip to develop with.
Thanks again Peter. I'll keep trying but it's not looking good.
Best regards,
Dan
short s = 0x1234;
char c_msb = (s >>> 8) & 0xFF; //this is an unsigned shift right, so the & 0xFF can be omitted
char c_msb = (s >> 8) & 0xFF; //this is a signed shift right, so the & 0xFF is required
char c_lsb = (s & 0xFF); //assign lower byte to char
To assemble two chars into a single short/int:
short sa = (short)((c_msb << 8) | (c_lsb)); //this assumes highbyte of chars are 0. You must cast to short.
regards peter
Dan
See here:
http://tech.groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/peripheral/memory/
Dynamic memory is implemented using an abstract class, meaning the heap can be located
anywhere as long as you provide the byte read/write functions.
It even supports heaps within heaps.
regards peter
I tried your code and it does not work for chars that end up higher than 80.
Please try the following code:
short s = 0x00c2;
char c_msb = (char)((s >> 8) & 0xFF);
char c_lsb = (char)(s & 0xFF);
short sa = (short)((c_msb << 8) | (c_lsb));
Note I had to cast the expressions using (char), it will not compile otherwise.
The watch window shows the following after this:
short s = 194 0x00C2 '..'
char c_msb 0 0x00 '.'
char c_lsb 65474 0xFFC2 '.'
short sa = 65474 0xFFC2 '..'
It appears that casting it to a char is what breaks it. The bitwise and is within the parentheses, before it gets cast.
Dan
import stamp.core.*;
public class ShortToChar_test {
· static short s = 0x00c2;
· static int i_msb = (s >> 8) & 0xFF;
· static int i_lsb = s & 0xFF;
· static char c_msb = (char)i_msb;
· static char c_lsb = (char)i_lsb;
· static short i_sa = (short)((c_msb << 8) | (c_lsb & 0xFF));
· static short c_sa = (short)((c_msb << 8) | (c_lsb));
· static void main() {
··· System.out.println(i_msb);······· //0
··· System.out.println(i_lsb);······· //194
··· System.out.println(i_sa);········ //194
··· System.out.println((int)c_msb);·· //0
··· System.out.println((int)c_lsb);·· //-62
··· System.out.println(c_sa);········ //-62
··· while (true) {
··· }
· }
}
generates output
0·····//i_msb
194· //i_lsb
194· //i_sa
0···· //c_msb
-62· //c_lsb
-62· //c_sa
The trouble is that casting to char means the jvm calls javabytecode b2i which converts a byte to an int
(signed). So you can either use int (which takes the same memory storage as char) or add
the & 0xFF when assembling back to short.
I suggest you use int for scalar values, but·you can use array of char. Just add the & 0xFF when converting
the char to int.
regards peter
You say that int and char have the same storage(two bytes). How can I account for this? Does this render the heap and stack pointers inaccurate? I mean what I'm getting at, if I create a char[noparse][[/noparse]8192] array, and call Memory.freeMemory(), it's half the size as if I use int[noparse][[/noparse]8192].
Thanks for your help.
Dan
char c;
takes 2 bytes for storage, just as int (or any other type).
Arrays of char,
char[noparse]/noparse ca = new char[noparse][[/noparse]SIZE];
takes SIZE bytes plus 4 bytes overhead.
Arrays of int,
int[noparse]/noparse ia = new int[noparse][[/noparse]SIZE];
takes 2*SIZE bytes plus 4 bytes overhead.
My memory classes SystemRam (that uses a char array) and SystemRam2 (that uses an int array)
both provide byte read/write functions that operate on byte addresses. The functions
take care of the fact that an int is 2 bytes (in array storage).
So using SystemRam with char[noparse][[/noparse]8192] is the same as using SystemRam2 with int[noparse][[/noparse]4096].
To assemble 2 bytes/chars to an int, you use
int i = mem.readByte(addr) | (mem.readByte(addr+1) << 8); (Little Endian storage)
Note that my readByte function returns an int value, which prevents
the issue of converting char to short/int all together, while still allowing
to store/retrieve char values in the heap.
regards peter
Thanks for all your help.
Dan