C job interview - casting and comparing

后端 未结 10 716
没有蜡笔的小新
没有蜡笔的小新 2021-02-01 12:29

I was confronted with a tricky (IMO) question. I needed to compare two MAC addresses, in the most efficient manner.

The only thought that crossed my mind in that moment

10条回答
  •  日久生厌
    2021-02-01 13:05

    There is nothing wrong with an efficient implementation, for all you know this has been determined to be hot code that is called many many times. And in any case, its okay for interview questions to have odd constraints.

    Logical AND is a priori a branching instruction due to short-circuit evaluation even if it doesn't compile this way, so lets avoid it, we don't need it. Nor do we need to convert our return value to a true bool (true or false, not 0 or anything that's not zero).

    Here is a fast solution on 32-bit: XOR will capture the differences, OR will record difference in both parts, and NOT will negate the condition into EQUALS, not UNEQUAL. The LHS and RHS are independent computations, so a superscalar processor can do this in parallel.

    int isEqual(MAC* addr1, MAC* addr2)
    {
        return ~((*(int*)addr2 ^ *(int*)addr1) | (int)(((short*)addr2)[2] ^ ((short*)addr1)[2]));
    }
    

    EDIT
    The purpose of the above code was to show that this could be done efficiently without branching. Comments have pointed out this C++ classifies this as undefined behavior. While true, VS handles this fine. Without changing the interviewer's struct definition and function signature, in order to avoid undefined behavior an extra copy must be made. So the non-undefined behavior way without branching but with an extra copy would be as follows:

    int isEqual(MAC* addr1, MAC* addr2)
    {
        struct IntShort
        {
            int   i;
            short s;
        };
    
        union MACU
        {
            MAC addr;
            IntShort is;
        };
    
        MACU u1;
        MACU u2;
    
        u1.addr = *addr1; // extra copy
        u2.addr = *addr2; // extra copy
    
        return ~((u1.is.i ^ u2.is.i) | (int)(u1.is.s ^ u2.is.s)); // still no branching
    }
    

提交回复
热议问题