С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.81/21: Рейтинг темы: голосов - 21, средняя оценка - 4.81
 Аватар для dopleref
42 / 52 / 33
Регистрация: 15.12.2015
Сообщений: 199

Приведение структуры к uint32_t

24.08.2017, 14:49. Показов 4559. Ответов 22
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!
Есть переменная пользовательского типа, представляющая собой
структуру размером 32 байта, хочу получить ее значение в переменной типа uint32_t,
как это лучше сделать?

Структура
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef struct
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
    uint32_t interface  : 3;
    uint32_t number     : 8;
    uint32_t command    : 9;
    uint32_t type       : 9;
    uint32_t nodata     : 3;
#elif __BYTE_ORDER == __BIG_ENDIAN
    uint32_t nodata     : 3;
    uint32_t type       : 9;
    uint32_t command    : 9;
    uint32_t number     : 8;
    uint32_t interface  : 3;
#else
#error "__BYTE_ORDER not defined"
#endif
}
abtci_protocol_header;
Хочу сделать что то типа такого (пример понятное дело не работает):
C++
1
2
abtci_protocol_header header;
uint32_t id = (uint32_t) header;
1
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.08.2017, 14:49
Ответы с готовыми решениями:

Как побитово скопировать uint32_t в float, минуя при этом выделения uint32_t в оперативную память
Всем привет, недавно заинтересовал такой вопрос ниже. Как ПОБИТОВО скопировать uint32_t в float, минуя при этом выделения uint32_t в...

Преобразовать uint8t* to uint32_t
Всем привет туплю и никак не могу правильно решить задачу на вход подается буфер формата 1 - 0x00 0x00 0x00 0x01 0x00 0x00 0x00...

uint32_t this decimal constant is unsigned only in ISO C90
Пишу так: uint32_t i=2147483648; Компилятор выдает: this decimal constant is unsigned only in ISO C90 И работает как со знаковой...

22
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.08.2017, 14:57
Лучший ответ Сообщение было отмечено dopleref как решение

Решение

dopleref,
C++
1
2
3
4
abtci_protocol_header header;
uint32_t id;
static_assert(sizeof header == sizeof id, "sizes not the same");
std::memcpy(&id, &header, sizeof id);
4
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
24.08.2017, 14:57
dopleref, Я сам не делал такого, но думаю, нужно двигаться в сторону перегрузки преобразования пользовательских типов
1
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
24.08.2017, 15:14
Цитата Сообщение от dopleref Посмотреть сообщение
структуру размером 32 байта
32 бита?
0
 Аватар для dopleref
42 / 52 / 33
Регистрация: 15.12.2015
Сообщений: 199
25.08.2017, 08:19  [ТС]
Добавлено через 10 секунд
Цитата Сообщение от TRam_ Посмотреть сообщение
32 бита?
Да 32 бита, извините глупая ошибка

Цитата Сообщение от DrOffset Посмотреть сообщение
C++
1
std::memcpy(&id, &header, sizeof id);
Спасибо, буду использовать Ваш вариант.

Цитата Сообщение от Bretbas Посмотреть сообщение
нужно двигаться в сторону перегрузки преобразования пользовательских типов
Посмотрел, хороший вариант, позволяет точно определить как будет происходить преобразование типов,
но в данном случае я не могу менять код определяющий используемую структуру.

Хотел просто как нибудь 'скастовать', но похоже без memcpy или оператора приведения типа тут не обойтись.
Спасибо большое за ответы!
0
 Аватар для dopleref
42 / 52 / 33
Регистрация: 15.12.2015
Сообщений: 199
28.08.2017, 10:37  [ТС]
Если кому-то интересно, нашел еще такой вариант используя 'кастование':
C++
1
uint32_t v = *reinterpret_cast<uint32_t*>(&header);
0
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
28.08.2017, 11:26
Цитата Сообщение от dopleref Посмотреть сообщение
не могу менять код определяющий используемую структуру
Можно использовать объединения:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
union U
{
    abtci_protocol_header h;
    int n;
};
 
    U u ={};
    int num;
 
    u.h.nodata = 1;
    num = u.n;  // 0x20000000
 
    u.h.nodata = 2;
    num = u.n;  // 0x40000000
 
    u.h.nodata = 4;
    num = u.n;  // 0x80000000
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
28.08.2017, 14:47
Цитата Сообщение от dopleref Посмотреть сообщение
Если кому-то интересно, нашел еще такой вариант используя 'кастование':
Так лучше не надо.
Делайте через memcpy,
как посоветовал DrOffset.

Alex5, такой подход - ub.
1
73 / 69 / 38
Регистрация: 09.10.2012
Сообщений: 238
28.08.2017, 20:31
Цитата Сообщение от Croessmah Посмотреть сообщение
Так лучше не надо.
Делайте через memcpy,
как посоветовал DrOffset.
А можно подробней? Правильно понимаю, что это UB? Т.е. разыменование преобразованного указателя.

Цитата Сообщение от Croessmah Посмотреть сообщение
Alex5, такой подход - ub.
И тут поясните пожалуйста, почему UB.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
28.08.2017, 21:05
Цитата Сообщение от mishelle92 Посмотреть сообщение
А можно подробней?
Цитата Сообщение от mishelle92 Посмотреть сообщение
И тут поясните пожалуйста
Приведение указателя базового типа
0
73 / 69 / 38
Регистрация: 09.10.2012
Сообщений: 238
28.08.2017, 21:29
Croessmah, и все же. Хочу разобраться.

1. Чем reinterpret_cast хуже memcpy (будем считать, что sizeof(uint32_t) == sizeof(abtci_protocol_header))?
2. Про union. UB - запись в одно поле и чтение из другого?
0
73 / 69 / 38
Регистрация: 09.10.2012
Сообщений: 238
29.08.2017, 23:17
Мне кажется я видел достаточно много кода с применением union как в сообщении.

Добавлено через 9 минут
Цитата Сообщение от mishelle92 Посмотреть сообщение
Мне кажется я видел достаточно много кода с применением union как в сообщении.
Видимо перенесенный из C код. А reinterpret_cast плох тем, что из-за strict aliasing может быть UB.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.08.2017, 23:23
Цитата Сообщение от mishelle92 Посмотреть сообщение
А можно подробней? Правильно понимаю, что это UB? Т.е. разыменование преобразованного указателя.
https://habrahabr.ru/post/114117/

Цитата Сообщение от mishelle92 Посмотреть сообщение
Про union. UB - запись в одно поле и чтение из другого?
да.
1
73 / 69 / 38
Регистрация: 09.10.2012
Сообщений: 238
29.08.2017, 23:28
Цитата Сообщение от hoggy Посмотреть сообщение
https://habrahabr.ru/post/114117/
Да, читал, спасибо. Потому и спросил, чтоб удостоверится. В той же статье правда union и предлагают использовать (пример SwapWords) - несостыковка.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.08.2017, 23:32
Цитата Сообщение от mishelle92 Посмотреть сообщение
В той же статье правда union и предлагают использовать (пример SwapWords) - несостыковка.
с оговоркой, что это UB
1
73 / 69 / 38
Регистрация: 09.10.2012
Сообщений: 238
29.08.2017, 23:33
Цитата Сообщение от hoggy Посмотреть сообщение
с оговоркой, что это UB
Как-то упустил из виду. Теперь всё встало на свои места.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.08.2017, 00:30
mishelle92, читать из неактивного члена дозволяется если хранящиеся объекты layout-compatible.
9.5/1
In a union, at most one of the non-static data members can be active at any time, that is, the value of at
most one of the non-static data members can be stored in a union at any time.
[ Note: One special guarantee
is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout
structs that share a common initial sequence (9.2), and if an object of this standard-layout union type
contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of
standard-layout struct members
; see 9.2. —end note ]
В статье, однако, нет никакой оговорки насчет union (оно и понятно - статья совсем про другое), оговорка там про касты через указатели (т.е. через упомянутый выше reinterpret_cast).
Тем не менее, прием c union довольно прочно укоренился среди программистов и компиляторы, как правило, не мешают ожидаемомоу поведению. С точки же зрения теории тут не все так однозначно. Почитать советую правило 97 из книжки Стандарты программирования на С++ и вот этот пост на stackoverflow (за разумное время написать лучше вряд ли будет можно).

Про reinterpret_cast и strict aliasing есть еще вот такая статья: http://dbp-consulting.com/tuto... asing.html, почитай, она хорошо раскрывает в том числе и способ решения через union.

Но еще важное, о чем тут не сказали, alignment для bit-field - implementation defined, padding для bit-field - тоже.
9.6/1
Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined.
Поэтому, с точки зрения переносимости битовые поля ненадежное средство. Если нужна переносимость, лучше написать рукодельную реализацию с использованием сдвигов и тем же uint32_t в качестве базового типа.

В общем, что я хочу сказать: не надо пользоваться сомнительными способами, сознательно закладывать в код не очень чистые приемы. И если ты сходу не сможешь вспомнить все ограничения и оговорки, которые накладывают вышеупомянутые "хакерские" способы, то и не стоит их применять.
memcpy для известного на этапе компиляции размера на современных компиляторах превращается в одну или две инструкции. Можно сравнить: https://godbolt.org/g/k4PtzL. Никакой потери эффективности не будет в большинстве случаев, при полном сохранении корректности кода. Без оговорок и спорах об UB.
4
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
30.08.2017, 11:49
Цитата Сообщение от Croessmah Посмотреть сообщение
такой подход - ub.
Croessmah, Вы имеете в виду пункт 9.5 стандарта или что-то другое?

Цитата Сообщение от DrOffset Посмотреть сообщение
the value of at most one of the non-static data members can be stored in a union at any time.
Croessmah, DrOffset, "only one can be stored" - "только одно может храниться". Здесь нет запрещения читать из другого поля.

C++
1
2
3
4
5
6
7
8
union U{
  int a, b, c;
} u;
u.a = 100; u.b = 200; u.c = 300;  // только одно значение   can be stored 
// это не мешает нам прочитать любой член объединения
cout << u.a << endl;  // 300 
cout << u.b << endl;  // 300 
cout << u.c << endl;  // 300
Добавлено через 30 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
не надо пользоваться сомнительными способами, ...
memcpy ...DrOffset, при полном сохранении корректности кода
DrOffset, с учетом сказанного о bit-field, сомнительность всех трех способов (memcpy, reinterpret_cast, union) одинакова.

Может кто-нибудь привести пример компилятора, на котором значения n1, n2, n3 будут различны?
C++
1
2
3
4
5
6
7
8
9
union U{
  int a, b, c;
} u;
u.a = 100; u.b = 200; u.c = 300;  
 
int n1, n2, n3; 
n1 = u.a;
memcpy( & n2, &u, sizeof(int) );
n3 = * reinterpret_cast<int*>(&u);
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
n1 = u.a;
011D16F3 8B 45 F8         mov         eax,dword ptr [u] 
011D16F6 89 45 EC         mov         dword ptr [n1],eax 
memcpy( & n2, &u, sizeof(int) );
011D16F9 6A 04            push        4    
011D16FB 8D 45 F8         lea         eax,[u] 
011D16FE 50               push        eax  
011D16FF 8D 4D E0         lea         ecx,[n2] 
011D1702 51               push        ecx  
011D1703 E8 01 FA FF FF   call        @ILT+260(_memcpy) (11D1109h) 
011D1708 83 C4 0C         add         esp,0Ch 
n3 = * reinterpret_cast<int*>(&u);
011D170B 8B 45 F8         mov         eax,dword ptr [u] 
011D170E 89 45 D4         mov         dword ptr [n3],eax
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.08.2017, 12:09
Alex5, твой пример как раз попадает под "One special guarantee", т.е. это точно легальный код.
Что касается разных типов, то тут все сложнее.
Да, стандарт явно не пишет, что, дескать такое использование union - undefined behaviour, но и при этом и не регламентирует это поведение (за исключением специально оговоренных layout-compatible типов). Т.е. стандарт дает гарантии насчет одинаковых типов (см. определение common initial sequence), но ничего не говорит насчет разных. Можно привести контр-пример:
C++
1
2
3
4
5
6
7
union U{
  int a;
  double c;
} u;
 
u.a = 100;
// что будет при чтении с?
Очевидно, что поведение не определено, т.к. разрядность и layout хранимых типов несовместимы.
В более простых случаях, когда мы можем implementation-defined способами обеспечить совместимость типов - это будет работать (например, как в твоем примере на первой странице). Но это не означает автоматически легальность. Это означает, что мы для нашей реализации все учли и получили (для нашей реализации) предсказуемое поведение. Да, мы молодцы и это работает. Но стандарт на это гарантий нам не дал.

И еще, прошу, прежде чем продолжать, изучить все материалы, ссылки на которые я дал. Возможно это снимет часть вопросов.

Добавлено через 3 минуты
Цитата Сообщение от Alex5 Посмотреть сообщение
DrOffset, с учетом сказанного о bit-field, сомнительность всех трех способов (memcpy, reinterpret_cast, union) одинакова.
С точки зрения работы с bit-field - да. Поэтому я и написал, что переносимый способ - это делать упаковку бит сдвигами.
Однако дискуссия уже перешла в другую плоскость, где отдельно обсуждаются собственные проблемы reinterpret_cast, и отдельно - собственные проблемы union. Это надо учитывать. А вот memcpy собственных проблем не имеет (ну, кроме потенциального оверхеда на вызов функции).
0
17 / 16 / 3
Регистрация: 18.08.2017
Сообщений: 54
30.08.2017, 14:09
Цитата Сообщение от Alex5 Посмотреть сообщение
"only one can be stored" - "только одно может храниться". Здесь нет запрещения читать из другого поля.
А как можно читать из поля, которое не хранится? (за искл. исключений для полей из common initial sequence для layout-compatible структур).

Цитата Сообщение от DrOffset Посмотреть сообщение
пример как раз попадает под "One special guarantee", т.е. это точно легальный код.
Guarantee даётся для структур в union-е. А int — не структура.
Можно ли относиться к типу T как к структуре с единственным полем типа T, по аналогии с тем, как стандарт в некоторых аспектах позволяет относиться к переменным не-массивам как к массивам с одним элементом?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.08.2017, 14:09
Помогаю со студенческими работами здесь

Помещение структуры в вектор, удаление структуры, изменение элементов структуры
Здравствуйте. Помогите разобраться с тем, как: 1 - находить элементы в векторе зная уникальный элемент структуры. 2 - удалять...

Приведение структуры матрицы к ленточной
Добрый вечер, извините за наглость, но не мог бы кто-нибудь помочь? естественно не за просто так. Задали курсовик делать, а мозгов не...

Рефлексия: как происходит приведение из object в производные классы и структуры
Объясните пожалуйста, даю кусок кода из книги Шилдта + 1-2 метода дописанных самостоятельно: using System; using System.Reflection;...

SysTick_GetPeriod(uint32_t frequency)
Как правильно? uint32_t SysTick_GetPeriod(uint32_t frequency) { return (system_GetCoreClock() / frequency); } или ...

C + IAR + uint32_t to char
Не уверен что в нужную тему вопрос, по истине детский. #ymstude &lt;stdint.h&gt; #ymstude &lt;stdlib.h&gt; ... uint32_t FREQ_SIT =...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru