Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

replace byte in 32 bit number

Tags:

c

I have a function called replaceByte(x,n,c) that is to replace byte n in x with c with the following restrictions:

  • Bytes numbered from 0 (LSB) to 3 (MSB)
  • Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
  • You can assume 0 <= n <= 3 and 0 <= c <= 255
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 10

    int replaceByte(int x, int n, int c) {
            int shift = (c << (8 * n));
            int mask = 0xff << shift;
            return (mask & x) | shift;
        }
    

but when I test it I get this error:

ERROR: Test replaceByte(-2147483648[0x80000000],0[0x0],0[0x0]) failed... ...Gives 0[0x0]. Should be -2147483648[0x80000000]

after realizing that * is not a legal operator I have finally figured it out...and if you are curious, this is what I did:

int replaceByte(int x, int n, int c) {
  int mask = 0xff << (n << 3);
  int shift = (c << (n << 3));
  return (~mask & x) | shift;
}
like image 530
asdfghjkl Avatar asked Apr 12 '12 22:04

asdfghjkl


3 Answers

Proper solution is for c = 0 as well:

     int replaceByte(int x, int n, int c)
     {
        int shift = 8 * n;
        int value = c << shift;
        int mask = 0xff << shift;

        return (~mask & x) | value;
     }
like image 69
M.Firlej Avatar answered Oct 08 '22 00:10

M.Firlej


Ahh... You are almost there.

Just change

return (mask & x) | shift; 

to

return (~mask & x) | shift;

The mask should contain all ones except for the region to be masked and not vice versa.

I am using this simple code and it works fine in gcc

#include<stdio.h>

int replaceByte(int x, int n, int c) 
{
    int shift = (c << (8 * n));
    int mask = 0xff << shift;
    return (~mask & x) | shift;
}

int main ()
{

    printf("%X",replaceByte(0x80000000,0,0));

    return 0;
}
like image 32
Pavan Manjunath Avatar answered Oct 08 '22 01:10

Pavan Manjunath


Since this looks like homework I'm not going to post code, but list the steps you need to perform:

  1. Cast c into a 32-bit number so you don't lose any bits while shifting
  2. Next, shift c by the appropriate number of bits to the left (if n==0 no shifting, if n==1 shift by 8 etc.)
  3. Create a 32-bit bitmask that will zero the lowest 8 bits of x, then shift this mask by the same amount as the last step
  4. Perform bitwise AND of the shifted bitmask and x to zero out the appropriate bits of x
  5. Perform bitwise OR (or addition) of the shifted c value and x to replace the masked bits of the latter
like image 7
Praetorian Avatar answered Oct 08 '22 01:10

Praetorian