Shop OBEX P1 Docs P2 Docs Learn Events
short to char — Parallax Forums

short to char

Dan DavisDan Davis Posts: 18
edited 2008-02-20 04:30 in General Discussion
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

Comments

  • Dan DavisDan Davis Posts: 18
    edited 2008-02-19 18:31
    Even worse.


    char b = 128; // b = 128 (0x80)
    char a = 127; // a = 127 (0x7F)
    a++; // a = 65408 (0xFF80)

    This is killing me! Help!

    Dan
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-02-19 18:55
    ALL single instances of any type (boolean,byte,char,short,int,reference) take two bytes.
    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
  • Dan DavisDan Davis Posts: 18
    edited 2008-02-19 19:09
    Thanks for your response 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
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-02-19 19:42
    To convert short to two chars:
    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 DavisDan Davis Posts: 18
    edited 2008-02-19 19:49
    Thanks Peter. I will give it a try. Like I mentioned above, I needed a class for dynamic memory allocation for my application. I'm sure I'm not the only one who could use it. One of the main points is a "free" function that can let go of strings or arrays as needed. It's primitive like C++, but better than nothing! Is there a place I can post it to share with other users?

    Dan
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-02-19 20:03
    These classes are already available.
    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
  • Dan DavisDan Davis Posts: 18
    edited 2008-02-20 02:42
    Hi 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
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-02-20 03:41
    The following program

    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
  • Dan DavisDan Davis Posts: 18
    edited 2008-02-20 04:04
    Well the "two chars" that I've been speaking about are actually two elements in a character array that is 8192 in size.

    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
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-02-20 04:27
    Single char values as in
    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
  • Dan DavisDan Davis Posts: 18
    edited 2008-02-20 04:30
    I understand. Interesting. I will take a closer look at that tomorrow, might be the approach I'll take.

    Thanks for all your help.

    Dan
Sign In or Register to comment.