문제

I have the following code for getting the MSB (Most Significant Bit) from a non-negative integer, Int32 to be more specific:

private static readonly int[] powersOf2 = new int[]
                                        {
                                            1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
                                            32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
                                            8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912,
                                            1073741824
                                        };

public static int GetMsb(int value)
{
    for (int k = powersOf2.Length - 1; k >= 0; k--)
    {
        var bit = (value & powersOf2[k]) != 0;
        if (bit)
            return (k + 1);
    }
    return 0;
}

Again: given that value is not negative.

My question is:
Does the .NET framework guarantee that this code would run appropriately on every platform: x86/Windows/Linux/Sun/64bit?

Is the Int32 representation inside .NET, including Endianness and bit/byte order, platform agnostic?

Thanks in advance!
BTW, if this is kind of a duplicate - please comment about it ASAP. Thanks!

도움이 되었습니까?

해결책

As long as you treat it as an int, yes it is platform agnostic. This includes all arithmetic and bitwise (<< , >> etc) operations. The opcodes always make sure that it does what you expect.

However! If you peek below the covers, it might matter; for example BitConverter.GetBytes(int) and BitConverter.ToInt32 care about the endianness. You can check this with BitConverter.IsLittleEndian; it is usually true on "regular" .NET, but could be false perhaps on IA64, or XNA or Mono on some architectures.

The same logic applies to any unsafe code that coerces (for example) between byte* and int*, or any unions constructed via [StructLayout].

But in regular code, you should be fine.

다른 팁

The endianness is platform dependent, but your code here doesn't depend on endianness at all.

Endianness only comes into play when you use low level stuff like pointers, unions(StructLayout:Explicit) or BitConverter.

Bitshifts, integer arithmetic and normal casts between integer types are endian agnostic.

Your code will always work.

That's not because the representation of Int32 won't change from platform to platform, but because your code is well-written enough not to rely on it: you are ANDing Int32s with other Int32s. In the event that the format did change, the change would affect both the number you're testing, and the entries in your powers-of-2 table, equally - so the code would still work.

The code is portable, however, it returns 0 as the MSB for int.MinValue wich is in fact 0x80000000 in hexa, because you're working with signed integers. Here is a code that works for all bits, I believe, and does not need any precalculated values:

public static int GetMsb(int value)
{
    for(int i = 31; i >= 0; i--)
    {
        if ((value & 0x80000000) != 0) return i;
        value <<= 1;
    }
    return 0;
}

or with a uint:

public static int GetMsb(uint value)
{
    for(int i = 31; i >= 0; i--)
    {
        if ((value & 0x80000000) != 0) return i;
        value <<= 1;
    }
    return 0;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top