Here's one attempt, assuming I got the requirements right:
int topbit(unsigned int x)
{
    for (int i = CHAR_BIT * sizeof x - 1; i >= 0; --i)
    {
        if (x & (1u << i))
            return i;
    }
    return -1;
}
unsigned int alignedxor(unsigned int a, unsigned int b)
{
    const int topa = topbit(a);
    const int topb = topbit(b);
    if (topa < 0)
        return b;
    if (topb < 0)
        return a;
    if (topa > topb)
        return a ^ (b << (topa - topb));
    return (a << (topb - topa)) ^ b;
}
int main(void) {
    printf("%x\n", alignedxor(0xce, 6));
    printf("%x\n", alignedxor(6, 0xce));
    return 0;
}
This prints e, twice, which seems correct but that's all the testing I did.
And yes, you can get the index of the topmost 1-bit more efficiently, but who cares? Also used my rich imagination to deal with corner cases (such as one number being 0).