С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/9: Рейтинг темы: голосов - 9, средняя оценка - 5.00
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
1

"Проецирование" массива байт на структуру

26.01.2017, 12:32. Показов 1886. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Допустим, есть некая структура и массив байт. Безопасно и корректно ли будет кастовать массив к структуре, чтоб удобно управлять нужными байтами через структуру?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <vector>
 
#pragma pack (push, 1)
struct T
{
   int   a;
   long b;
   char c;
};
#pragma pack (pop)
 
void send_ready_data(const std::vector<char>& v)
{
    // some actions
}
 
int main()
{
   const int data_size = 13
   std::vector<char> vec(data_size);
   
   T* some_struct; 
   some_struct = reinterpret_cast<T*>(vec.data());
   some_struct->a = 123;
   some_struct->b = 321;
   some_struct->c = 0xAA;
 
   send_ready_data(vec);
     
   return 0;
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.01.2017, 12:32
Ответы с готовыми решениями:

Проецирование массива в память
Доброго времени суток. Мне надо проецировать файл с массивом в память. #include &lt;windows.h&gt;...

Как заставить программу принимать цепочку байт из оперативной памяти, в виде массива байт ?
В памяти процесса есть закодированный блок с байтами, есть адрес этого блока и размер. Есть так-же...

Вычесть из одного массива байт другой массив байт
Здравствуйте! Подскажите что нужно сделать чтобы из одного массива байт вычесть другой массив байт!

Массив байт преобразовать в структуру
Всем привет. Нужна помощь с маршалингом структуры. Необходимо массив байт преобразовать в...

13
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,876
26.01.2017, 12:56 2
Цитата Сообщение от Selot Посмотреть сообщение
Безопасно и корректно ли будет кастовать массив к структуре, чтоб удобно управлять нужными байтами через структуру?
Формально - нет.
0
Модератор
Эксперт С++
13710 / 10910 / 6476
Регистрация: 18.12.2011
Сообщений: 29,133
26.01.2017, 12:58 3
Цитата Сообщение от Selot Посмотреть сообщение
vec.data()
У вектора нет метода прямого доступа к данным.
Более того, vec[0] и vec[1] не обязаны находиться друг за другом.

А вот к char[13] можете применить эту методику без зазрения совести.
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
26.01.2017, 13:02 4
Цитата Сообщение от zss Посмотреть сообщение
У вектора нет метода прямого доступа к данным.
http://en.cppreference.com/w/c... ector/data

Добавлено через 49 секунд
Разве не оно?
0
Модератор
Эксперт С++
13710 / 10910 / 6476
Регистрация: 18.12.2011
Сообщений: 29,133
26.01.2017, 13:04 5
С оговоркой:
(since C++11)
0
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,876
26.01.2017, 13:30 6
Цитата Сообщение от zss Посмотреть сообщение
Более того, vec[0] и vec[1] не обязаны находиться друг за другом.
В векторе как раз таки обязаны. Формальное отсутствие такой гарантии в самой первой версии С++98 было сразу признанно дефектом и исправлено еще тогда.
1
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
26.01.2017, 13:31  [ТС] 7
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Формально - нет.
такая запись - UB?
Цитата Сообщение от zss Посмотреть сообщение
Более того, vec[0] и vec[1] не обязаны находиться друг за другом.
а разве вектор не аллоцирует непрерывный кусок памяти? он ведь позиционируется, как замена массива
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.01.2017, 14:17 8
Лучший ответ Сообщение было отмечено Selot как решение

Решение

Цитата Сообщение от zss Посмотреть сообщение
Более того, vec[0] и vec[1] не обязаны находиться друг за другом.
обязаны

Добавлено через 3 минуты
Цитата Сообщение от Selot Посмотреть сообщение
Безопасно и корректно ли будет кастовать массив к структуре, чтоб удобно управлять нужными байтами через структуру?
в данном случае - корректно.
однако за свои удобства вы заплатите эффективностью.
доступ к полям пакованной структуры может быть намного медленнее,
чем доступ к структуре с выравниванием.
2
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,876
26.01.2017, 19:41 9
Цитата Сообщение от Selot Посмотреть сообщение
Безопасно и корректно ли будет кастовать массив к структуре, чтоб удобно управлять нужными байтами через структуру?
В языке С++ из нетривиальных реинтерпретаций разрешается только реинтепретировать любой объект, как массив char или unsigned char (с целью чтения или модификации через массив char или unsigned char). Но не наоборот. Обратная реинтерпретация не допускается, т.е. не допускается реинтерпретация массива байтов, как объекта другого типа. То есть именно то, что вы пытаетесь делать - формально недопустимо.

Понятно, что такие драконовские ограничения не дают нам возможности даже создавать свои аллокаторы, но формально ограничения именно таковы.
1
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
27.01.2017, 11:20  [ТС] 10
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
не допускается реинтерпретация массива байтов, как объекта другого типа.
Цитата Сообщение от hoggy Посмотреть сообщение
в данном случае - корректно.
Так где грань между "можно" и "нельзя"?
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
27.01.2017, 11:35 11
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Обратная реинтерпретация не допускается, т.е. не допускается реинтерпретация массива байтов, как объекта другого типа.
на этом основана конструкция множества различных врапперов,
которые аллоцируют объекты во внутренних чаровых хранилищах,

хотите сказать, что следующий код содержит UB?

http://rextester.com/MRZ31868

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
//-std=c++14 -fopenmp -O2 -g3 -pedantic -Wall -Weffc++ -Wextra 
//-Woverloaded-virtual -Wctor-dtor-privacy -Wnon-virtual-dtor 
//-Wold-style-cast -Wconversion -Wsign-conversion -Winit-self 
//-Wunreachable-code
 
int main() 
{
    struct sample
    {
        std::string text = "hello, CyberForum";
    };
    
    char buff[ sizeof(sample)];
    
    new(buff)sample;
    
    auto* ptr = reinterpret_cast<sample*>(buff);
    std::cout << ptr->text << std::endl;
}
1
25 / 25 / 5
Регистрация: 04.01.2017
Сообщений: 52
29.01.2017, 16:48 12
hoggy, можете объяснить что в этой строке
C++
1
new(buff)sample;
происходит?
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
29.01.2017, 16:58 13
FHelio,
Надеюсь хогги не сильно обидется если я отвечу за него
Это placement new
После new можно поставить круглые скобки и передать туда участок памяти в котором должен быть размещен объект sample
На этот участок памяти в данном случае указывает buff. Память куда указывает buff должен быть не менее чем sizeof(sample) что бы вместить экземпляр класса
1
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
30.01.2017, 11:46 14
Цитата Сообщение от FHelio Посмотреть сообщение
можете объяснить что в этой строке
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
 
//-std=c++14 -fopenmp -O2 -g3 -pedantic -Wall -Weffc++ -Wextra 
//-Woverloaded-virtual -Wctor-dtor-privacy -Wnon-virtual-dtor 
//-Wold-style-cast -Wconversion -Wsign-conversion -Winit-self 
//-Wunreachable-code
 
int main() 
{
    struct sample
    {
        std::string text = "hello, CyberForum";
    };
 
    // создаём обычный массив байт такой
    // что б туда гарантированно влез
    // объект структуры  
    char buff[ sizeof(sample)];
    
    // создаем объект 
    // но не в динамической памяти
    // а по указанному нами адресу
    // (то бишь выделения памяти не происходит)
    // называется "размещающий new" (new placement)
    new(buff)sample;
 
 
    // извлекаем из массива типа char
    // объект типа  sample  
    auto* ptr = reinterpret_cast<sample*>(buff);
 
    // получаем доступ к методам объекта
    std::cout << ptr->text << std::endl;
 
    // ВАЖНО:
    // обратите внимание - объект реально существует в  массиве
    // однако, с точки зрения компилятора 
    // это простой массив типа char
    // и при его разрушении, 
    // никаких диструкторов вызвано не будет
    // привет, утечки ресурсов!!!
 
    // тот редкий случай, 
    // когда нужно вызывать диструктор вручную
    ptr->~sample();
}
3
30.01.2017, 11:46
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.01.2017, 11:46
Помогаю со студенческими работами здесь

Скопировать массив байт в структуру
Доброе время суток! Помогите пожалуйста разобраться с такой вот проблемой - есть структура с...

Число типа real (6 байт). Сделать структуру данных которая показала бы значение каждого байта этого числа
Люди очень срочно, прошу помогите. Дано число типа Real (6 байт). Зделать структуру данных...

Найти максимальный элемент массива и записать его в Rg BH (формат элементов массива - байт).
Помогите пожалуйста написать программу на ассемблере. Буду очень сильно благодарен. Найти...

Десериализация массива байт
Json объект представлен в бинарном виде и хранится в массиве байт. Как его десериализовать и...

Шифрование массива байт
можете подсказать код с алгоритмом шифрования больших массивов байт?(4к+ элементов) я пытаюсь...

Буферизация массива байт
Нужно реализовать вот такую ​​штуку: из сети частями приходят массивы байт, и нужно все эти массивы...

Обьявление массива байт
Подскажите, плз, а как объявить и задать массив байтов? Максимум что у меня получилось это типа...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru