Combining several variables into one

This is a discussion on Combining several variables into one within the C++ Programming forums, part of the General Programming Boards category; For those of you that read the game forum here, you might have seen that I have been interested in ...

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485

    Combining several variables into one

    For those of you that read the game forum here, you might have seen that I have been interested in how speed up some graphics functions I have.

    From reading this article I learned that it is possible to take two 16bit variables and store them in a 32 bit variable. But I am not really sure how to do this, so here are some questions:

    When you assign the two variables to the bit one, is it done like this:
    The first 16bit variable is stored in the front, and the second in the back? So the two variables are not added together, they are just stored in the same place.

    100 and 100 would not be 200, but 100100?

    Code:
                 size of 32bit                
            /                              \
          /                                  \
     size of 16bit     size of 16bit 
    I have made a small test program where I try to place two chars in one int, but I cant get it to work. Could anyone give me a helping hand or point me to a place where I can read up on this?

    Code:
    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    int main () 
    {
    
    	char a = 0;
    	char b = 25;
    	char c = 50;
    	char d = 75;
    
    	int test = b | (c << 4);
    
    	test = test * 2;
    
    	cout <<" size of char = " << sizeof(char) << endl;
    	cout <<" size of int  = " << sizeof(int) << endl;
    
    	cout << " a = " << (int)a << endl;
    	cout << " b = " << (int)b << endl;
    	cout << " c = " << (int)c << endl;
    	cout << " d = " << (int)d << endl;
    
    	cout << endl;
    
    	cout << "b = " << (test >> 8) << endl;
    	cout << "c = " << (test >> 4) << endl;
     
    	system("Pause");
    	return 0;
    }
    Thank you

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    1,609
    This is what the bitshift operators are for.

    Check out the macros MAKELONG(16bit, 16bit), LOWORD(32bit), and HIWORD(32bit).
    A class that doesn't overload all operators just isn't finished yet. -- SmugCeePlusPlusWeenie
    A year spent in artificial intelligence is enough to make one believe in God. -- Alan J. Perlis

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    What about a struct?

  4. #4
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    Yes, it would (in concept) be 100100.

    Taking that example, you could multiply the first 100 by 1000, and then add them for saving. In practice, since you are using 16 bit values, you would add 2^16 to the first value and then add (or OR) the two together.

    To break the values up later on, you could use the modulo operator, or shift, or AND.

    Todd
    Mac and Windows cross platform programmer. Ruby lover.

    Quote of the Day
    12/20: Mario F.:I never was, am not, and never will be, one to shut up in the face of something I think is fundamentally wrong.

    Amen brother!

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    2,027
    It may be better to just use the short type, and let the compiler optimize it for you, If you use binary operators, then you cannot take advantage of the machine commands designed for accessing high and low register parts.

    Using a struct of two shorts (with a good compiler) may make it easier for the compiler notice the opportunity for optimization.

    Using compiler macros, if they exist, is the best solution for this, as those will be optimized as best as possible for the compiler; they are likely stand-ins for the machine commands.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  6. #6
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Quote Originally Posted by h3ro View Post
    Code:
    	int test = b | (c << 4);
    You are only shifting left by 4, yet a char is (usually) 8 bits. So you are overlapping the two values, losing their identities.

  7. #7
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    This is what the bitshift operators are for.

    Check out the macros MAKELONG(16bit, 16bit), LOWORD(32bit), and HIWORD(32bit).
    Do I need to include anything to get them to work? I just got errors. Im using visual studio 2008

    What about a struct?
    What I want is calculating two screen pixels at the same time. Im not sure that I can do that with a struct?

    Yes, it would (in concept) be 100100.
    When I do: int test = a | ( b <<8 );
    I get this:
    Code:
       b       a
    1011010   10001
    
         test
    101101000010001
    Where does the extra zeros between the numbers come from?

    When do sizeof() of a int and on a char I get 4 and 1. Does that mean that I can add four chars in an int?
    I tried doing it like this: a | ( b <<8 ) | (c<<16);
    But that did not work.

    Also, how do I get the value of a after I added them? I can get b, but not sure about a.

    Here is my code now:
    Code:
    int main () 
    {
    	char a = 17;
    	char b = 90;
    
    	int test = a | ( b <<8 );
    
    	test *=2;
    
    	cout <<" size of char = " << sizeof(char) << endl;  // 1
    	cout <<" size of int  = " << sizeof(int) << endl;   // 4
    
    	cout << endl;
    
    	cout << " a    = " << (int)a << endl;
    	cout << " b    = " << (int)b << endl;
    	cout << " test = " << (int)test << endl;
    
    	cout << " newA = " << (int)(test>>8) << endl;
    	cout << " newB = " << (int)(test>>16) << endl;
    
    	cout << endl;
    
    	cout << " a | b = " << (a | b) << endl;
    	cout << " a ^ b = " << (a ^ b) << endl;
    	cout << " a & b = " << (a & b) << endl;	
    	cout << " a ^ a = " << (a ^ a) << endl;	 // Always zero
     
    	system("Pause");
    	return 0;
    }
    Thanks a lot for the help so far

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    [quote="h3ro"]
    When do sizeof() of a int and on a char I get 4 and 1. Does that mean that I can add four chars in an int?
    I tried doing it like this: a | ( b <<8 ) | (c<<16);
    But that did not work
    [/code]
    It should do. Although it's probably more reliable if you have unsigned chars that you work on.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    CSharpener vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,484
    Where does the extra zeros between the numbers come from
    They are not between, they are inside - each char has 8 binary digits, you just skipped the leading zeroes.
    a is not 10001, it is 00010001
    The first 90% of a project takes 90% of the time,
    the last 10% takes the other 90% of the time.

  10. #10
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    i had to make a gradient function a while ago. probably not the fastest, but it definitely does the kind of thing you want to do here.

    color data is stored as 0x00BBGGRR

    Code:
    int * __fastcall gradient(int *colors,const int size,int c0,int cf)
    {
            byte r0 = (byte)c0;
            byte g0 = (byte)(c0>>8);
            byte b0 = (byte)(c0>>16);
            byte rf = (byte)cf;
            byte gf = (byte)(cf>>8);
            byte bf = (byte)(cf>>16);
            for(int i=0;i<size;i++)
            {
                    int R = ((size-i)*r0+i*rf)/size;
                    int G = ((size-i)*g0+i*gf)/size;
                    int B = ((size-i)*b0+i*bf)/size;
                    G*=0x00000100;
                    B*=0x00010000;
                    colors[i] = R+G+B;
            }
    }

  11. #11
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Thank you for the code m37h0d. But I am not 100% sure what is going on there. Do you know of any code that does roughly the same but has more comments or a good article?

    Code:
    	unsigned char a = 17;
    	unsigned char b = 90;
    	unsigned char c = 50;
    
    	unsigned int test = a | (b <<8) | (c <<16);
    How do I print out the value of a,b and c by using test?

  12. #12
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Quote Originally Posted by h3ro View Post
    Thank you for the code m37h0d. But I am not 100&#37; sure what is going on there. Do you know of any code that does roughly the same but has more comments or a good article?

    Code:
    	unsigned char a = 17;
    	unsigned char b = 90;
    	unsigned char c = 50;
    
    	unsigned int test = a | (b <<8) | (c <<16);
    How do I print out the value of a,b and c by using test?
    Code:
    printf("a = %d\n", test & 0xff);
    printf("b = %d\n", (test >> 8) & 0xff);
    printf("c = %d\n", (test >> 16) & 0xff);
    EDIT: Once again I forgot which board I'm on. Same basic idea, but matsp's is actually in C++

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    cout << "a = " << (test & 0xff) << endl;
    cout << "b = " << ((test >> 8) & 0xff) << endl;
    cout << "c = " << ((test >> 16) & 0xff) << endl;
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    Quote Originally Posted by h3ro View Post
    Thank you for the code m37h0d. But I am not 100% sure what is going on there. Do you know of any code that does roughly the same but has more comments or a good article?

    Code:
    	unsigned char a = 17;
    	unsigned char b = 90;
    	unsigned char c = 50;
    
    	unsigned int test = a | (b <<8) | (c <<16);
    How do I print out the value of a,b and c by using test?
    sorry i don't. my basic understanding is this:

    an int is 32 bits, or 4 bytes.

    a byte, or char, is 8 bits.

    casting an int to char or byte will simply truncate the int's data to the least significant 8 bits.

    bit shifting does essentially what the name implies, it reorders the bits in the operand.

    as someone will undoubtedly point out, i'm probably off in some of the details, but this is how i understand the process currently.

  15. #15
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Thank you. I did not know that I had to AND it with 255.

    Is there a difference between using hex and decimals, or is it just that that is how its down when working with bits?

    Now I have 4 chars in a int. But I tried putting 8 chars in a __int64, and it did not work out to good.

    Code:
           unsigned __int64 test = a | (b <<8) | (c<<16) | (d<<24) | (e<<32) | (f<<40) | (g<<48) | (h <<56);
    
    	cout << " newA = " << (test & 0xff) << endl;
    	cout << " newB = " << ((test >> 8) & 0xff) << endl;
    	cout << " newC = " << ((test >> 16) & 0xff) << endl;
    	cout << " newD = " << ((test >> 24) & 0xff) << endl;
    	cout << " newE = " << ((test >> 32) & 0xff) << endl;
    	cout << " newF = " << ((test >> 40) & 0xff) << endl;
    	cout << " newG = " << ((test >> 48) & 0xff) << endl;
    	cout << " newH = " << ((test >> 56) & 0xff) << endl;
    I have read that c++ does not have a standard 64bit value, so is this simply impossible?

Page 1 of 3 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. basic question about global variables
    By radeberger in forum C++ Programming
    Replies: 0
    Last Post: 04-06-2009, 12:54 AM
  2. Replies: 15
    Last Post: 09-30-2008, 02:12 AM
  3. esbo's data sharing example
    By esbo in forum C Programming
    Replies: 49
    Last Post: 01-08-2008, 10:07 PM
  4. Combining variables into one string
    By g001 in forum C++ Programming
    Replies: 2
    Last Post: 11-08-2007, 12:17 AM
  5. Replies: 6
    Last Post: 01-02-2004, 12:01 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21