1

I don't understand *p++ &= 0xFF; in the following code. Why does the operator &= appear here?

unsafe void Foo(int[,] arr)
{
    int length = arr.Length;
    fixed (int* b = arr)
    {
        int* p = b;
        for (int i = 0; i < length; i++)
         *p++ &= 0xFF;
    }
}
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
KrzT
  • 27
  • 1
  • 7
  • It's just another assignment operator, like +=, but for &. https://msdn.microsoft.com/en-us/library/aa691314(v=vs.71).aspx – Bill the Lizard Aug 15 '17 at 17:23
  • dereferencing p, incrementing p, anding with FF(256) and assigning this result back to p. Compiler output shoud be same with readable form of `p[i]=p[i]&256;` – huseyin tugrul buyukisik Aug 15 '17 at 17:23
  • It is the `AND` [bitwise operator](https://en.wikipedia.org/wiki/Bitwise_operation#AND) – Gilad Green Aug 15 '17 at 17:23
  • https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/and-assignment-operator –  Aug 15 '17 at 17:24
  • The variable type is int which is four bytes. So the code is moving four bytes (p++) and only keeping the least significant byte by ANDing the integer with 0xFF. – jdweng Aug 15 '17 at 17:28
  • @huseyintugrulbuyukisik and assigning the result back to where p used to point – pm100 Aug 15 '17 at 17:34
  • @pm100 you are right. Where it points. Otherwise would be disasterous. But it is easily corrected with `p[i]=p[i]&256;` which comes afterwards. – huseyin tugrul buyukisik Aug 15 '17 at 17:38

6 Answers6

2

It is an another assignment operator

x &= y

is

x = x & y  

In this case, you are incrementing p adding with FF and assigning to p

Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
1

So you've probably seen something like a += b //a = a + b.

This is essentially the same thing just with a bitwise comparison operator &. Specifically, the user here is getting the inverse binary value for p (I THINK, someone correct me please) in the form of 2's compliment.

See here for a good example of bitwise comparison, first answer: Understanding the behavior of a single ampersand operator (&) on integers

Capn Jack
  • 1,201
  • 11
  • 28
1

It performs bitwise and operation to each element of the array.

For example, if p[i] = 256, it will become 0; if p[i] = -1, it will become 255; if p[i] = -2, it will become 254.

 256: 00000001 0000000
0xFF: 00000000 1111111
======================
   0: 00000000 0000000

  -1: 11111111 1111111
0xFF: 00000000 1111111
======================
 255: 00000000 1111111

  -2: 11111111 1111110
0xFF: 00000000 1111111
======================
 254: 00000000 1111110
adamyi
  • 547
  • 2
  • 15
1

It will round all array contents to be in range [0,255] by performing AND bitwise operation.

nebras.w
  • 11
  • 2
1
// for example: we are passing array with 4 elements (arr[2,2])

unsafe static void Foo (int[,] arr)
{
    int length = arr.Length; // length == 4

    fixed (int* b = arr) // b is a pointer to the first element of the 'arr' array (pointer is of type int)
    {
        int* p = b; // lets copy pointer to a new variable (we will change that variable in a loop)
                    // we cannot change 'b', because it is a 'fixed' variable

        for (int i = 0; i < length; i++) // iterate over all 'arr' elements (4 elements)
            *p++ &= 0xFF; // *p = *p & 255   - it means we will use only 8 low bits from 32 bit int, all 'arr' values stay between [0..255]
                          // p = p + 4 (because int is 4 bytes)
                          // now p is a pointer to the second element in the 'arr' (each element in the arr is of size 4 bytes)

        // *p =   10101101 10101101 10101101 10101101
        // & 255  00000000 00000000 00000000 11111111
        // =      00000000 00000000 00000000 10101101
    }
}
apocalypse
  • 5,764
  • 9
  • 47
  • 95
1

They get the least significant bytes from each item in the array *p++ gets the value pointed by p and set p to the next address the value obtained is a 32 bit integer

lhs &= rhs is equivalent to lhs = lhs & rhs;

0xFFFF - 32 bits 0xFF - 16 bits

0xFFFF & 0xFF == 0xFFFF & 0x00FF

X & 0 is 0 so they are converting the first 16 bits to zero getting only the least significant bits