О реализации "GetBytes" в BitConverter - PullRequest
6 голосов
/ 30 декабря 2011

Я обнаружил, что реализация функции GetBytes в .net Framework выглядит примерно так:

public unsafe static byte[] GetBytes(int value)
{
   byte[] bytes = new byte[4];
   fixed(byte* b = bytes)
     *((int*)b) = value;
   return bytes;
}

Я не уверен, что понимаю все подробности этих двух строк:

   fixed(byte* b = bytes)
     *((int*)b) = value;

Может ли кто-нибудь дать более подробное объяснение здесь? И как мне реализовать эту функцию в стандарте C ++?

Ответы [ 5 ]

4 голосов
/ 30 декабря 2011

Может ли кто-нибудь дать более подробное объяснение здесь?

Документация MSDN для fixed поставляется с многочисленными примерами и пояснениями - если этого недостаточно, вам необходимо уточнить, какую именно часть вы не понимаете .


А как мне реализовать эту функцию в стандарте C ++?

#include <cstring>
#include <vector>

std::vector<unsigned char> GetBytes(int value)
{
    std::vector<unsigned char> bytes(sizeof(int));
    std::memcpy(&bytes[0], &value, sizeof(int));
    return bytes;
}
0 голосов
/ 30 декабря 2011

Вы можете реализовать GetBytes () для любого типа POD с помощью простого шаблона функции.

#include <vector>

template <typename T>
std::vector<unsigned char> GetBytes(T value)
{
    return std::vector<unsigned char>(reinterpret_cast<unsigned char*>(&value),
                                      reinterpret_cast<unsigned char*>(&value) + sizeof(value));
}
0 голосов
/ 30 декабря 2011

Функция создает байтовый массив, который содержит те же двоичные данные, что и целочисленное представление вашей платформы value. В C ++ это может быть достигнуто (для любого типа) следующим образом:

int value; // or any type!
unsigned char b[sizeof(int)];
unsigned char const * const p = reinterpret_cast<unsigned char const *>(&value);
std::copy(p, p + sizeof(int), b);

Теперь b - это массив байтов размером с тип int (или тип, который вы использовали).

В C # вам нужно сказать fixed, чтобы получить необработанный указатель, поскольку обычно у вас нет необработанных указателей в C # из-за объектов, не имеющих фиксированного расположения в памяти - сборщик мусора может перемещать их в любой время. fixed предотвращает это и фиксирует объект на месте, так что необработанный указатель может иметь смысл.

0 голосов
/ 30 декабря 2011

Необходимо использовать первое исправленное, потому что мы хотим назначить указатель на управляемую переменную:

Оператор fixed не позволяет сборщику мусора перемещать подвижная переменная. Фиксированное утверждение допускается только в небезопасных контекст. Фиксированный также можно использовать для создания буферов фиксированного размера.

Оператор fixed устанавливает указатель на управляемую переменную и "pins" эта переменная во время выполнения оператора. Без фиксированного, указатели на подвижные управляемые переменные будут бесполезны, так как сборка мусора может непредсказуемо переместить переменные. The Компилятор C # позволяет только назначить указатель на управляемую переменную в фиксированное утверждение. Ref .

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

Затем мы приводим указатель к байту к указателю на int, разыменовываем его и присваиваем ему переданному int.

0 голосов
/ 30 декабря 2011

Исправлено говорит сборщику мусора не перемещать управляемый тип, чтобы вы могли получить доступ к этому типу с помощью стандартных указателей.

В C ++, если вы не используете C ++ / CLI (то есть не используете .NET), вы можете просто использовать указатель размера в байтах (char) и проходить через байты во всем, что вы пытаетесь преобразовать.

Просто помните о порядке байтов ...

...