3

Could somebody explain why the value of c variable is not 0x0c in code below:

function test() {
    byte b = 0x2c;
    byte c;
    assembly {
        c := and(b, 0xf)
    }
    Check(c);
}

The Check event shows 0x00 instead.

But code below works correctly:

function test() {
    byte b = 0x2c;
    byte mask = 0x0f;
    byte c;
    assembly {
        c := and(b, mask)
    }
    Check(c);
}

The value of c is 0x0c.

3

This is about the way that Solidity byte types are represented for use in the EVM: byte types are all left-justified within a 32-byte word, i.e. a single byte type is left-shited by 31 * 8 = 248 bits before being put on the stack.

In your first example, variable b is a single-width byte type so it is put on the stack as 0x2c00000000000000000000000000000000000000000000000000000000000000. However, 0xf has no particular type, so it is put on the stack as 0x0f, which is the same as 0x000000000000000000000000000000000000000000000000000000000000000f. The logical and of these is clearly zero.

In your second example, both of the operands to and are explicitly byte types, therefore Solidity computes: 0x2c00000000000000000000000000000000000000000000000000000000000000 & 0x0f00000000000000000000000000000000000000000000000000000000000000, and then it reports the single byte result c in the Check event (the left-most byte of the result, since that's how bytes are stored in Solidity).

The Remix IDE debugger is very helpful for stepping through code like this to see what's going on under the hood. If you are going to use some assembly code I highly recommend it - as you can see there are some surprises.

  • You are absolutely right! More than, I suggest do not use byte in that case at all - using uint takes less gas for the same procedures. – Val Dubrava Aug 10 '17 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.