Безопасность интерпретации целого числа как массива байтов

#c #ios #endianness

#c #iOS #порядковый номер

Вопрос:

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

Вместо преобразования int64_t значения в символьную строку, безопасно ли переосмысливать его как двоичную строку для транспортировки … затем обратно в int64_t по прибытии?

на клиенте..

 int64_t timeValue = 1554532128;
std::basic_string<char> timeString((const char *)timeValue, sizeof(int64_t));
  

а затем на сервере..

 std::basic_string<char> timeString;
int64_t timeValue = (int64_t)(*timeString.data());
  

Комментарии:

1. Вместо std::basic_string<char> я бы предпочел использовать std::vector<uint8_t> или std::array<uint8_t,8> , но с тем же порядком окончания его должно быть безопасно использовать для транспортировки.

2. Безопасно это или нет, зависит от того, как вы отправляете строку и строите строку из полученных данных.

3. Я думаю, что это неправильно int64_t timeValue = (int64_t)(*timeString.data()); , лучше int64_t timeValue = *(int64_t*)(timeString.data());

4. Я использую grpc для связи двух процессов, и иногда, когда мне нужно отправить структуру, и я не хочу определять ее в прототипе (или это может быть одна из нескольких возможных структур, которые четко определены как POD), я использую этот метод. Я просто устанавливаю строковый параметр и создаю его именно таким образом. Следует позаботиться о создании строк с данными и размером , а не просто передавать char* . Тем не менее, я также обязательно проверяю это sizeof(expected_struct) == str.size() на принимающей стороне (вы должны сделать sizeof(int64_t) == timeString.size() , чтобы знать, что с вами все в порядке).

Ответ №1:

Безопасно использовать char* указатель для доступа к необработанным байтам переменной, стандарт C предусматривает такое использование. Но вы неправильно преобразуете свои значения с обеих сторон. Вместо этого код должен выглядеть примерно так:

 int64_t timeValue = ...;
std::string timeString(reinterpret_cast<char*>(amp;timeValue), sizeof(int64_t));
  

 std::string timeString = ...;
//assert(timeString.size() == sizeof(int64_t));
int64_t timeValue = *reinterpret_cast<int64_t*>(timeString.data());