Solved

store ints in shorts...

Posted on 1998-06-10
23
426 Views
Last Modified: 2010-04-15
Ok, I give up. I am trying to store an integer (assuming 4 bytes) in 2 shorts (assuming 2 bytes) and then get the integer back again. I tried memcpy()'s and this little bit of code with no luck.
... snip ...
short1 = int1;
short2 = (int1 >> 16) & 0xFFFF;
int2 = (int)((int)((short)short1) |
                  (int)((int)((short)short2) << 16));
... snip ...
Any help is appreciated. mm
0
Comment
Question by:marvinm
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 5
  • 3
  • +5
23 Comments
 
LVL 2

Expert Comment

by:abesoft
ID: 1251154
Why not do it like this:

union myUnion{
    int theInt;
    struct{
        short one;
        short two;
    } theAlias
} myVar;
myVar.theInt = int1;

And then you can access myVar.theAlias.one (and two) to get at the data.

This keeps your code portable and all that, although it doesn't really account for what happens when sizeof(int) == sizeof( short).  If you want to cover yourself in that case, you should initialize the whole union to 0 when you start.

Hope this helps.
0
 
LVL 1

Author Comment

by:marvinm
ID: 1251155
I need to store an integer in 2 shorts, and then get an integer form the 2 shorts. I'm not worried about portability. I'm working on a windows machine. Big-Endian, Right?
Thanks, mm
0
 
LVL 4

Expert Comment

by:sganta
ID: 1251156
Hi Marvinm !

I have the solution for your problem. But unfortunately Question is locked.
This works fine. If it is acceptable to you. Please reject the earlier answer.
and accept it.

int int1,int2,int3,temp_int1,temp_int2;
short short1,short2,short3;

/* Assign some value to int1 */


short1 = (int1 >> 16) &0x00FF;       /* Stores the higher 2 bytes */
short2 = int1 & 0x00FF;                /* Stores the lower 2 bytes */

/* To get back the short1 & short2 into integer do the following */

temp_int1 = short1;  /* Or you can say temp_int1 = (int) short1; */
temp_int2 = short2;  

int3 = (temp_int1<<16)|temp_int2;


OR

You can replace the above statement by
int3 = ((int)short1)<<16 | ((int)short2);

The above solutions works fine. I hope this is acceptable to you.

Thank you for GOOD QUESTION.
JESUS LOVES YOU - sganta
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 3

Expert Comment

by:Norbert
ID: 1251157
a little bit much casting
first the length of int is not defined it depends on the machine
and the compiler
int can be 16 bit or 32 bit
therefore for comptibility
long int1;
long int2;
short short1;
short short2;
short1=(short)(int1&0x0ffff);
short2=(short)((int1>>16)&0x0ffff);
int2=((long)short2<<16)|(long)short1;
should work
example:
the long value
0x12345678
short1 contains 0x5678
short2 contains 0x1234
((long)short2<<16)=0x12340000;
what you coded shold work
so where is your problem ?
0
 
LVL 1

Author Comment

by:marvinm
ID: 1251158
This program results in:
before <99867> after <65563>
int main(void)
{
      short s1,s2;
      int   i1,i2;

      i1 = 99867;
      s1 = (i1 >> 16) & 0x00FF;
      s2 = i1 & 0x00FF;
      i2 = ((int)s1) << 16 | ((int)s2);
      printf("before <%d> after <%d>\n",i1,i2);
      return 0;
}

0
 
LVL 4

Expert Comment

by:sganta
ID: 1251159
Have you tested my answer
Which I had posted as a COMMENT
0
 
LVL 1

Author Comment

by:marvinm
ID: 1251160
sganta:
The program I posted above as a comment is essentially your answer, isn't it? - mm
0
 
LVL 4

Expert Comment

by:sganta
ID: 1251161
Yes ! Now I am posting as an answer.

      I have the solution for your problem. But unfortunately Question is locked.
      This works fine. If it is acceptable to you. Please reject the earlier answer.
      and accept it.

      int int1,int2,int3,temp_int1,temp_int2;
      short short1,short2,short3;

      /* Assign some value to int1 */


      short1 = (int1 >> 16) &0x00FF;       /* Stores the higher 2 bytes */
      short2 = int1 & 0x00FF;                /* Stores the lower 2 bytes */

      /* To get back the short1 & short2 into integer do the following */

      temp_int1 = short1;  /* Or you can say temp_int1 = (int) short1; */
      temp_int2 = short2;  

      int3 = (temp_int1<<16)|temp_int2;


      OR

      You can replace the above statement by
      int3 = ((int)short1)<<16 | ((int)short2);

      The above solutions works fine. I hope this is acceptable to you.

      Thank you for GOOD QUESTION.
      JESUS LOVES YOU - sganta
0
 
LVL 1

Author Comment

by:marvinm
ID: 1251162
sganta:
if I set int1 to 99867, then intt3 becomes 65563?
0
 
LVL 4

Expert Comment

by:sganta
ID: 1251163
Hi !

Can you try this.

int3 = ((temp_int1<<16)& 0Xff00)|(temp_int2 & 0X00FF)

I 've checked my earlier solution but it works fine.
OK, You try this. I hope this should work.
0
 
LVL 1

Author Comment

by:marvinm
ID: 1251164
That comes out with 27 for 99867. I've tested on a windows 95, and an SCO UNIX box.
0
 
LVL 4

Expert Comment

by:sganta
ID: 1251165
Can you display the output values
for short1,short2,temp_int1,temp_int2
and get back to me.
Thanks
0
 
LVL 2

Expert Comment

by:abesoft
ID: 1251166
I'm not sure how my answer missed your question, but I thought that you wanted to get at the contents of an int as two shorts...

Taking my union:
    union myUnion{
        int theInt;
        struct{
            short one;
            short two;
        } theAlias;
    } myVar;

You could re-write the code from your original question:
short1 = int1;
short2 = (int1 >> 16) & 0xFFFF;
int2 = (int)((int)((short)short1) |
                  (int)((int)((short)short2) << 16));
to read:
myVar.theInt = int1;
/* Now, read or set myVar.theAlias.one */
short1 = myVar.theAlias.one;
short2 = myVar.theAlias.two;
int2 = myVar.theInt;

So, my question is: what am I missing?  What are you trying to do that I wasn't providing?  Did you really want to use that many casts....
If you like casts, try
    short1 = (*(myUnion*) &int1).theAlias.one;
    short2 = (*(myUnion*) &int1).theAlias.two;

0
 
LVL 1

Author Comment

by:marvinm
ID: 1251167
short1 = tmp_int1 = 1
short2 = tmp_int2 = 27
0
 
LVL 1

Author Comment

by:marvinm
ID: 1251168
abesoft:
All the casting was just to try to fix what wasn't working.
My problem is the way that I was storing an int in 2 shorts, and then creating an int was not working. Using your union idea is fine; however, I was looking for a response as to why my code failed. Thanks, mm
0
 
LVL 16

Expert Comment

by:imladris
ID: 1251169
I'm not quite clear on why sganta's code is not providing you with the result you're after.

However, as to the why, the crux of the problem lies in how shifting and sign extension work. When a short is cast to an int, since they are both signed, sign extension will occur. So an short which has the top bit set (which therefore appears to be a negative number) will propogate that through the top 16 bits when it is cast to an int (so that it will also be negative).

The other snare in this kind of stuff is that if you left shift a short by 16 it will wind up being 0. You have to be sure to cast it to an int before the shift occurs.

0
 

Accepted Solution

by:
PhilC earned 100 total points
ID: 1251170
You could use a character buffer inbetween
int integer1,integer2;
short short1,short2;
char buf[10];

memcpy(buf,&integer1,sizeof(int));
memcpy(&short1,buf,sizeof(short));
memcpy(&short2,buf+sizeof(short),sizeof(short));
memcpy(buf,&short1,sizeof(short));
memcpy(buf+sizeof(short),short2,sizeof(short));
memcpy(&integer2,buf,sizeof(int));

here integer1 = integer2.
0
 
LVL 84

Expert Comment

by:ozo
ID: 1251171
short1 = int1;
short2 = (int1 >> 16);
int2 = (short1&0xffff) | (short2<<16);

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1251172
sganta's code used 0x00ff instead of 0xffff (ie one byte instead of two).

0
 
LVL 1

Author Comment

by:marvinm
ID: 1251173
Still no luck. I was sing 0xffff, it dont work.
ozo, I get the same incorrect results from your solution. (It is essentially the code I posted, without all the casts.
Using an intermediate character buffer works, but seems like there should be another way.
0
 
LVL 84

Expert Comment

by:ozo
ID: 1251174
are you saying that
  long int1=99867;
  short short1 = int1;
  short short2 = (int1 >> 16);
  long int2 = (short1&0xffff) | (short2<<16);
  printf("%ld\n",int2);
gives 27?
I don't understand how a conforming c compiler can do that.
please tell us what you get from
  printf("%ld\d",int2 = (short1&0xffff));
  printf("%ld\n",int2 = (short2<<16));

0
 
LVL 1

Author Comment

by:marvinm
ID: 1251175
Ozo: you're answer worked fine, I'm not sure how I tested it, but I must have screwed something up. The buffer answer works fine and is the easiest for me to understand. I'm still not clear on how the bitwise operations come up with the correct answer.

Sganta's answer comes up with the answer 27. Here's what I finally tested, and the output:
#include <stdio.h>

int main(void)
{
  int int1=99867,int2,tmp_int1,tmp_int2;
  short short1,short2;

  printf("my origional:\n");
  short1=int1;
  short2=(int1>>16) & 0xFFFF;
  int2=(int)((int)((short)short1)|(int)((int)((short)short2)<<16));
  printf("short1 <%d> short2 <%d> int1 <%d> int2 <%d>\n",short1,short2,
                                                                int1,int2);
  printf("sganta first:\n");
  short1=(int1>>16) & 0x00FF;
  short2=int1&0x00FF;
  int2=((int)short1<<16)|short2;
  printf("short1 <%d> short2 <%d> int1 <%d> int2 <%d>\n",short1,short2,
                                                                int1,int2);
  printf("sganta second:\n");
  tmp_int1=short1;
  tmp_int2=short2;
  int2=((tmp_int1<<16)&0xff00)|(tmp_int2&0x00FF);
  printf("short1 <%d> short2 <%d> int1 <%d> int2 <%d>\n",short1,short2,
                                                                int1,int2);
  printf("ozo first:\n");
  short1=int1;
  short2=(int1>>16);
  int2=(short1&0xffff)|(short2<<16);
  printf("short1 <%d> short2 <%d> int1 <%d> int2 <%d>\n",short1,short2,
                                                                int1,int2);
  return 0;
}
my origional:
short1 <-31205> short2 <1> int1 <99867> int2 <-31205>
sganta first:
short1 <1> short2 <27> int1 <99867> int2 <65563>
sganta second:
short1 <1> short2 <27> int1 <99867> int2 <27>
ozo first:
short1 <-31205> short2 <1> int1 <99867> int2 <99867>
0
 
LVL 84

Expert Comment

by:ozo
ID: 1251176
Well, in yoour original, (int)short1 sign extended from 0x861b to 0xffff861b.
(int)((unsigned short)short1) could have fixed that.

sganta first has the problem that RONSLOW pointed out.
using 0xFF instead of 0xFFFF made 0x861b&0xff = 0x1b
sganta second repeats the problem and also makes 0x1b0000&0xff00 = 0

my first undoes the sign extend with (int)short1&0xffff
(or using unsigned shorts could have obviated the need for that)

the memcpy version could be simplified to

   memcpy(&short1,&integer1,sizeof(short));
   memcpy(&short2,(char *)&integer1+sizeof(short),sizeof(short));

   memcpy(&integer2,&short1,sizeof(short));
   memcpy((char *)&integer2+sizeof(short),&short2,sizeof(short));
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.
Suggested Courses

627 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question