Solved

store ints in shorts...

Posted on 1998-06-10
23
418 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
  • 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
 
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
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
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.

708 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now