Thread: Could someone explain this code for me please...

  1. #1
    *this
    Join Date
    Mar 2005
    Posts
    498

    Could someone explain this code for me please...

    I found this while looking through the blowfish encryption algorithm, I am looking for techniques for my own and I dont quite understand this portion:

    Code:
    struct WordByte
    {
    	unsigned int three:8;
    	unsigned int two:8;
    	unsigned int one:8;
    	unsigned int zero:8;
    };
    
    union Word
    {
    	unsigned int word;
    	WordByte byte;
    };
    I know that the union type Word can be accessed as a WordByte, and i take it that its somehow organized from 4 bytes with 8 bits each? how do these numbers relate? sorry I blanked.

  2. #2
    Work in Progress..... Jaken Veina's Avatar
    Join Date
    Mar 2005
    Location
    Missouri. Go Imos Pizza!
    Posts
    256
    Well, both type WordByte and type int take up the same space in memory: 4 bytes. Go ahead and run printf() statements for sizeof(WordByte) and sizeof(int). They're the same. And I assume you know how a union works.
    Code:
    void function(void)
     {
      function();
     }

  3. #3
    *this
    Join Date
    Mar 2005
    Posts
    498
    Ya, Im just confused with the :8 part. What does the ":" operator do in this situation?

  4. #4
    Banned
    Join Date
    Jun 2005
    Posts
    594
    my guess is 8 bits per byte

  5. #5
    *this
    Join Date
    Mar 2005
    Posts
    498
    Ya thats what I thought, thats it thanks

  6. #6
    *this
    Join Date
    Mar 2005
    Posts
    498
    Eh another question, I get it if theres one variable of 8 bits in WordByte but how does it distribute it among the 4 variables "zero, one, two, three" ?

  7. #7
    myNegReal
    Join Date
    Jun 2005
    Posts
    100
    I think it might be assigning the variables and initial value when the struct is instantiated.
    For example when calling a constructor or function you can put : and assign values. These will be assigned before the function body is called. For example:
    Code:
    // An example class
    class Fruit {
    public:
    	int size;
    	Color color; // assume Color is a class
    	Fruit (int size, Color color) {
    		this->size = size;
    		this->color = color;
    	}
    };
    When you create and instance of the class, by calling Fruit(5, aColorObject), the obvious happens, the constructor is called and the constructor body sets the size and color variables to those specified in the parameters. But instead of doing that you could write this:
    Code:
    Fruit(int size, Color color) : size(size), color(color) {}
    
    // When the constructor is called, it sets the variables after the : to the values specified in
    // the ()'s, and then would go on to execute the body, which is not necessary now
    // because we've moved the assignments after the : so you can leave that empty and just
    // put {}, however you can have a body in a function or constructor if you want.
    // Note that setting the variables to something in the body will override what you set them to
    // after the colon.
    Notice the syntax is a : after the constructor/function parameters (and after a const, if present) and following for each variable you put the variable_name(assigned_value) and a comma(,) after each assignment except the last one. Then the opening brace, body, which can be nothing, and closing brace. This can be used for a constructor or a function, but not a destructor.
    Also note that in the original constructor, since the class variable names and parameter names are the same we need to use this to distinguish that we mean the class variable, otherwise it would assume the parameter. But in the second constructor, we don't use this because you can only set variables within the class, so it knows that you mean the class variables.

    So my guess with that line unsigned int three:8 is giving it a default value of 8, rather than using the assignment operator. But I'm probably wrong :P

  8. #8
    *this
    Join Date
    Mar 2005
    Posts
    498
    Well you have good reasoning, I know what your saying, but when I check the values after storing a number in the union, i get either 0 or different numbers, I am pretty sure it has to do with bits, and that it assigns 8 bits to it, but I just dont know how the union chooses where to stick em.

  9. #9
    myNegReal
    Join Date
    Jun 2005
    Posts
    100
    I don't see how you can assign 8 bits to it. Unless you mean set the first(from left or right) 8 bits to 1. A byte is 8 bits, you can't change that, and an int takes up 4 bytes, which is 32 bits. You can't change how much the int takes up, and you can't change how much a byte takes up. The only thing I can see it doing with bits is setting them, 8 in this case.
    For example:
    An unsigned int set with no value:
    00000000000000000000000000000000 << those many bits would be reserved for the int when it is created. You can't make it only take up say 00000000, which you can't go lower than a byte(8 bits). So regardless of you're number, for example 2, in binary 10, only takes up 2 bits. But you can't just put 2 bits in memory you have to put the whole byte, which would give 8 bits, 6 leading zero's before the 10. And an int get 4 bytes, so you have 30 leading zero's to the 10. So what you're saying assigning 8 bits to it, you can't do that. The int is automatically assigned 4 bytes. Maybe it's setting bits?
    00000000000000000000000011111111 or
    11111111000000000000000000000000.
    I doubt that's the case.
    Edit: Also, with 8 bits per byte, a byte is already 8 bits, so that statement wouldn't be needed, so that's most likely not it. And the bits in the byte can only be 8, so you couldn't put anything else, so it'd be a useless statement, that's definately not it.

    Edit 2: I ran a little test, I found out what it's doing. It actually does have something to do with bits and assigning it to the int. The way I was thinking was wrong. Well, right in terms, if you put a number less than 8 it still allocates 4 bytes. You said it was some compression you were looking at? Well, that's the compression. What it's doing with the ints, by saying :n, it's compressing it by saying, allocate the 4 bytes, but do not allow any bits after nth bit to be changed from 0. So by saying :8, you're only allowing the first 8 bits to be changed. But here's what it's doing: the struct holds the 4 ints. Take out the :8 and each int will take up 4 bytes, and call sizeof() on the struct, it'll be 16 bytes. Makes sense. But, the compression is in relation to the struct. By saying 8 bits for each int, it doesn't need to allocate a whole 4 bytes that you're not gonna use. So it allocates the struct as if it were and int itself, using only 4 bytes (call sizeof() on the struct with :8's in). And each 8 bits of the 4 bytes are reserved for the ints. So basically you have an int in memory. And instead of reading the int itself, you use bitwise operators to extract the bits, and use the first 8 as one number, then 2nd as another and so on. That's what it's doing by itself. Since you're saying only use 8 bits for this int, and 4 of them are doing that, it's saying why not just allocate one int and read each byte as a different number. So when you set a value to one of these ints, it'll only change it's 8 bits in the int. So if you give a value like that will take more than 8 bits, it'll only set what it can leaving the rest of the int untouched. Also, like I said before, a int is 4 bytes, you're nicely seperating each int into a byte, making it take only and int. However if you add another int in there, regardless of it you only give it 8 bits or more or less, it'll allocate a whole 'nother int and the struct will take up 8 bytes. Also with just the 4, if you give each 16 bits, the struct will take 8 bytes. Try it, use the sizeof() function on the struct and try different values. I know this must be confusing as I didn't explain very well, and I only know what I got from running tests, I'm sure there's more indepth details about it. But I do know for sure that it's saying you only want to use 8 bits for the variable, and since you're doing that for all, you don't need the unnecessary extra 3 bytes, so the struct allocates one int to save space and stores the 4 values in that one. So it's a kind of compression on the struct by limiting how many bits you want the variables to take. If you understand bit-level stuff more and about bytes, and how to use bitwise operators you'd understand it more. Here's an example program that could store 4 numbers in a single int.
    Code:
    #include <iostream>
    #define UINT unsigned int
    using namespace std;
    
    int main() {
        UINT storage;
        storage |= 3411719529; // set some random bits to 1 and some to 0
        UINT val1 = storage & 255; // extract first 8 bits from the right
        UINT val2 = (storage & 65280) >> 8; // extract second set of 8 bits
        UINT val3 = (storage & 16711680) >> 16; // and so on..
        UINT val4 = (storage & 4278190080) >> 24; // bit shifts are to shift the 8 bits all the way
        // to the right to prevent any following zeroes from increasing the value
        cout<<"Value 1: "<<val1<<endl; 
        cout<<"Value 2: "<<val2<<endl;
        cout<<"Value 3: "<<val3<<endl;
        cout<<"Value 4: "<<val4<<endl;
        cin.get(); // to keep program open
    }
    Run it and look at the values you get. Obviously extracting the data creates a whole 'nother 4 bytes to store it, but this is just an example, and those 4 bytes would be temporary anyway.
    Last edited by Ganoosh; 06-22-2005 at 01:19 AM.

  10. #10
    *this
    Join Date
    Mar 2005
    Posts
    498
    I see what your saying, but test this program i just whipped up that only shows the first 8 bits, so the numbers are essentially only using 8 bits....

  11. #11
    *this
    Join Date
    Mar 2005
    Posts
    498
    I would post it here but the forums have a bug, whenever i put code tags it shouts no data etc... So ill try soon but i have source for a program where i show 32 bits in each integer and only the first 8 are used.

  12. #12
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Calling all guru's! Answer thy plee! (this threads question, wth is : for)

    I'd test by doing a simple:
    unsigned int zero:8;

    Then set it to say 5000, and bitshift it (and cout after each shift) to test the effects.. if I could even compile it:

    7 C:\Projects\dfdsfsdf.cpp syntax error before `:' token
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  13. #13
    *this
    Join Date
    Mar 2005
    Posts
    498
    Wow this is sweet i figured it out, what it does is it assigns up to the first 8 bits of the number to three, then pretending that its still assigning regular bits to three it just moves those down to two, then to one, then zero...lol this might sound confusing but heres what it would do:

    word value = 10000;
    10000 in binary is --> 10011100010000

    so...
    it assigns the first 8 bits (00010000) to three
    so three becomes 16

    then it assigns the next 8 bits or less (100111) to two
    so two becomes 39

    I did this using a test program i made where i showed the full binary of the word value, then showed the binary of each integer inside of wordbyte and found that it has just been shifted down to the next variable.

  14. #14
    myNegReal
    Join Date
    Jun 2005
    Posts
    100
    Lol Josh, I figured it out about half an hour before you did it just took me so long to explain it, look at my last post, it explains what is going on(pretty much what you said), but it also compresses the structure. And I gave an example program that does the same thing as the struct, but without the :8 thing.
    The program I posted is pretty much doing what the struct is doing. But depending on how much the variable is reserved and how many variables, making it more flexible and easy.
    Last edited by Ganoosh; 06-22-2005 at 01:25 AM.

  15. #15
    *this
    Join Date
    Mar 2005
    Posts
    498
    WoW didnt see that part of ur post haha.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Writing Code
    By ILoveVectors in forum C++ Programming
    Replies: 4
    Last Post: 06-13-2005, 12:27 AM
  2. True ASM vs. Fake ASM ????
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 04-02-2003, 04:28 AM
  3. Seems like correct code, but results are not right...
    By OmniMirror in forum C Programming
    Replies: 4
    Last Post: 02-13-2003, 01:33 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. Replies: 4
    Last Post: 01-16-2002, 12:04 AM