2

In Java:

I have a 32-bit number given to me in hexadecimal form. I'm given a specific byte number (0-3, 0 for least-significant byte) and told that I need to replace that byte with another byte also given to me in hexadecimal form. Ex: 32-bit number 0xAAA5BBC6, replace byte 1 with 0x17 to get 0xAAA517C6.

I can't use any casting, multiplication, addition, subtraction, or conditionals. I cannot write any helper methods, or call any other method from this or another file to implement any method. Additionally, this has to be written in one line of code.

I believe I should be using masking, but I can't figure out where to start. Given a byte number, how can I change all 8 bits. Toggling one off or on is easy, but toggling all 8 bits to be a certain value?

Myron King
  • 33
  • 4
  • 1
    Think about how you'd mask a single bit... then try to mask 8 consecutive bits the same way.. – Buddy Sep 02 '15 at 03:49
  • Look at the bitshift operators. Use them to move your bit mask into place. – Thilo Sep 02 '15 at 03:51
  • Just a note: the way bytes are numbered is _not_ universal. Usually, the low-order byte of a 32-bit number is called "byte 0", but I've seen it other ways--I've seen it called byte 3, with byte 0 being the high-order 8 bits, and I've even run across people who would call it byte 4. So when asking a question like this, it's best to clarify. If you don't know, then you need to ask the person who's telling you to do this. – ajb Sep 02 '15 at 04:27
  • Updated to state 0 for least-significant byte – Myron King Sep 02 '15 at 05:05

2 Answers2

1

Take a look at the following example:

input   =    AA      A5         BB      C6  (in hex)
input   = 10101010 10100101 10111011 11000110 (in binary)
mask    =    FF       FF       00       FF  (in hex)
mask    = 11111111 11111111 00000000 11111111 (in binary) 
-------------------------------------------------------
input   = 10101010 10100101 00000000 11000110 (bitwise AND)
replace =    FF       FF       17       FF  (in hex)
replace = 11111111 11111111 00010111 11111111 (in binary) 
-------------------------------------------------------
input   = 10101010 10100101 00010111 11000110 (bitwise OR)
input   =    AA      A5         17      C6  (in hex)

The last line is your desired output. As you can see, there are two bitwise operation, AND and OR. You have to study those a lot to know how the work.

mazhar islam
  • 5,561
  • 3
  • 20
  • 41
  • This helps a lot, thanks for the information @rakeb.void. We just started working with these operators in this sense. This seems pretty advanced. – Myron King Sep 02 '15 at 05:20
0

In one line, assuming that bytes are being counted from the least significative byte:

int updatedValue = originalValue & ~(0xFF << (byteNumber << 3)) | ((((int)newByte) & 0xFF) << (byteNumber << 3));

Where:
originalValue is your original 32-bit integer
newByte is the byte you are given to replace the old byte
byteNumber is the byte number (0-3)

what the code does is the following:

  • create a mask to "delete" the old byte (clear the bits of this byte). In order to create the mask:

    • create a mask of a byte of all bits set (all in 1) 0xFF
    • offset this mask to the position of the byte to be "deleted", it has to be 8 times the number of the byte to be "deleted". As I can't multiply (part of your restrictions), then I offset this number 3 bits to the left (which is equivalent to multiply by 8, remember that displacing the bits one position to the left is equilavent to multiply by 2, so an offset by 3 will be 2 * 2 * 2 = 8) this is done by this piece of code: (byteNumber << 3)
    • "toggle" the bits of the mask with ~, so I have the mask to "delete" the byte: ~(0xFF << (byteNumber << 3)) at this point you mask would be, say FFFF00FF if you wanted to clear byte #1
  • perform an and-bit-wise operation between the original number and the mask created in the first step: ~(0xFF << (byteNumber << 3))

  • create a 32bit integer with the new byte and offset its bits to the position of the byte. Again, the offset is done with (byteNumber << 3) which has already been explained.
  • perform an or bit-wise operation with the result of the second step to set the bits of the new byte (this is the line of code, the final step)

Now, the reason for which I'm doing ((int)newByte) & 0xFF) instead of just ((int)newByte)) or just newByte, is that the JVM promotes to int the operator byte before doing the operation <<, this can have undesired effects if your newByte is bigger than 0x7F (for instance, a value of 0x80 would be cast to int as 0xFFFFFF80 instead of 0x00000080). By doing ((int)newByte) & 0xFF) I'm doing the promotion to int by myself and clear undesired bits just in case.

morgano
  • 17,210
  • 10
  • 45
  • 56
  • This worked exactly @morgano. I just need to look at it for a it and try to understand exactly what's happening. It's starting to make a little more sense, especially when added rakeb.void's comments. – Myron King Sep 02 '15 at 05:18
  • I can't tell you how much this helped me out! I was able to solve the next problem in a fraction of the time! "Return the nybble from a 32-bit number given in hex and which nybble" return (num & (0xF << (which << 2))) >> (which << 2); – Myron King Sep 02 '15 at 12:47
  • I'm glad I was helpful ;-) – morgano Sep 02 '15 at 12:58