Как работает BitConverter.ToInt32? - PullRequest
11 голосов
/ 03 ноября 2011

Вот метод -

using System;

class Program
{
    static void Main(string[] args)
    {
        //
        // Create an array of four bytes.
        // ... Then convert it into an integer and unsigned integer.
        //
        byte[] array = new byte[4];
        array[0] = 1; // Lowest
        array[1] = 64;
        array[2] = 0;
        array[3] = 0; // Sign bit
        //
        // Use BitConverter to convert the bytes to an int and a uint.
        // ... The int and uint can have different values if the sign bit differs.
        //
        int result1 = BitConverter.ToInt32(array, 0); // Start at first index
        uint result2 = BitConverter.ToUInt32(array, 0); // First index
        Console.WriteLine(result1);
        Console.WriteLine(result2);
        Console.ReadLine();
    }
}

Вывод

16385 16385

Я просто хочу узнать, как это происходит?

Ответы [ 6 ]

14 голосов
/ 03 ноября 2011

Документы для BitConverter.ToInt32 на самом деле имеют довольно хорошие примеры.Предполагая, что BitConverter.IsLittleEndian возвращает true, array[0] - это наименее значимый байт, как вы показали ... хотя array[3] - это не просто знаковый бит, это самый значимый байт, который включает в себя знаковый бит (как бит 7), но остальные биты предназначены для величины.

Итак, в вашем случае младший байт равен 1, а следующий байт равен 64 - поэтомурезультат:

( 1 * (1 << 0) ) +    // Bottom 8 bits
(64 * (1 << 8) ) +    // Next 8 bits, i.e. multiply by 256
( 0 * (1 << 16)) +    // Next 8 bits, i.e. multiply by 65,536
( 0 * (1 << 24))      // Top 7 bits and sign bit, multiply by 16,777,216

, что составляет 16385. Если бит знака был установлен, вам нужно будет рассмотреть два случая по-разному, но в этом случае все просто.

4 голосов
/ 03 ноября 2011

Преобразуется, как если бы это было число в базе 256. Итак, в вашем случае: 1 + 64 * 256 = 16385

3 голосов
/ 03 ноября 2011

Глядя на .Net 4.0 Framework справочный источник , BitConverter работает так, как сказал ответ Джона , хотя для работы с массивом используются указатели (код unsafe) .

Однако, если второй аргумент (т.е. startindex) делится на 4 (как в вашем примере), фреймворк использует ярлык. Он берет указатель byte на value[startindex], преобразует его в указатель int и затем разыменовывает его. Этот прием работает независимо от того, является ли IsLittleEndian истинным.

На высоком уровне это в основном означает, что код указывает на 4 байта в массиве byte и категорически объявляет: «кусок памяти там есть int!» (а затем вернуть его копию). Это имеет смысл, если принять во внимание, что int - это просто кусок памяти.

Ниже приведен исходный код метода ToUint32:

return (uint)ToInt32(value, startIndex);
0 голосов
/ 28 ноября 2018

Вы можете посмотреть сами - https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,e8230d40857425ba

Если данные выровнены по словам, они просто приведут указатель памяти к int32.

return *((int *) pbyte);

В противном случае он использует побитовую логику из значений указателя байтовой памяти.

0 голосов
/ 23 ноября 2017

Для тех из вас, у кого проблемы с Литл Эндиен и Биг Эндиен.Я использую следующие функции оболочки, чтобы позаботиться об этом.

    public static Int16 ToInt16(byte[] data, int offset)
    {
        if (BitConverter.IsLittleEndian)
        {
            return BitConverter.ToInt16(BitConverter.IsLittleEndian ? data.Skip(offset).Take(2).Reverse().ToArray() : data, 0);
        }
        return BitConverter.ToInt16(data, offset);
    }

    public static Int32 ToInt32(byte[] data, int offset)
    {
        if (BitConverter.IsLittleEndian)
        {
            return BitConverter.ToInt32(BitConverter.IsLittleEndian ? data.Skip(offset).Take(4).Reverse().ToArray() : data, 0);
        }
        return BitConverter.ToInt32(data, offset);
    }

    public static Int64 ToInt64(byte[] data, int offset)
    {
        if (BitConverter.IsLittleEndian)
        {
            return BitConverter.ToInt64(BitConverter.IsLittleEndian ? data.Skip(offset).Take(8).Reverse().ToArray() : data, 0);
        }
        return BitConverter.ToInt64(data, offset);
    }
0 голосов
/ 03 ноября 2011

массив [0] = 1;// Самый низкий // 0x01
array [1] = 64;// 0x40
array [2] = 0;// 0x00
array [3] = 0;// знаковый бит 0x00

Если объединить каждое шестнадцатеричное значение 0x00004001

В документе MSDN все объясняется

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...