|
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
|
|||||||||||
Копировать char * в член неизвестной структуры20.12.2021, 18:24. Показов 3789. Ответов 30
Добрый вечер,
Допустим есть две структуры:
Сложность в том, что предполагается что CT1 неизвестная структура (в дальнейшем так будет). О структуре CT1 известно только сколько в ней членов, тип каждого члена и оффсеты до каждого члена (offsetof(CT1, x), offsetof(CT1, name), offsetof(CT1, family)). В дальнейшем мне надо будет структуру CT2 скопировать в CT1 при этом скопировать данные из char * в std::string. Не знаю решаема ли задача, но я для начала я хочу просто скопировать содержимое CT2.name в CT1.name используя оффсеты:
0
|
|||||||||||
| 20.12.2021, 18:24 | |
|
Ответы с готовыми решениями:
30
Копировать пустую строку в const char* Конструктор структуры (класса)
Обработать входящий JSON неизвестной структуры |
|
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
|
||||||||
| 22.12.2021, 19:42 [ТС] | ||||||||
|
Я исхожу из следующих соображений: в моем векторе есть баффер vec.data() (или &vec[i]), то есть байты информации. В данном случае если взять один элемент вектора (например нулевой) то там будет сидеть CT1 который представлен следующим образом: 0-7 байты это данные записанные как double 8-39 байты это std::string 40-71 байты это std::string Всего размер CT1 72 байта Из этих значений нетрудно определить оффсеты для каждого члена. Теперь при записи я передаю С библиотеке баффер vec.data() и говорю: 0-7 байты это H5T_NATIVE_DOUBLE 8-39 это H5T_C_S1 с пометкой H5T_VARIABLE (С библиотека такую строку воспринимает как char *, но стандартный размер для нее 8 байт) 40-71 это тоже строка Я записал такие нестандартные данные. Теперь хочу прочитать. Для чтения я указываю такие же офсеты и размер структуры. После того как я прочитал данные, я смотрю 8-39 байты. Я понимаю что Си библиотека прочитала все то, что я записал, но std::string занимает 32 байта, а char * 8. Насколько я знаю, std::string хранит в себе такой же указатель на массив как и char * и мне нужно правильно распорядиться этими 32 байтами. Я полагаю что Си библиотека хранит char * в 8-15 байтах, а остальные 24 байта заполнены мусором. Строчка кода memcpy(&str_ptr, (const char *) &vec[i] + member_offsets[member], sizeof(str_ptr)); как раз копирует указатель на char * в переменную str_ptr, таким образом я я из 32 байт выделил первые 8 и "воспринял" их как char *.Затем у std::string есть конструктор который на вход принимает const char *. Строка *reinterpret_cast<std::string *>((char *) &vec[i] + member_offsets[member]) = str_ptr; на мой взгляд в левой части интерпретирует 8-39 байты как std::string, а в правой части я присваиваю char *, то есть неявно использую коструктор std::string(const char *). На мой взгляд получается что то типо
Если мой тупизм зашкаливает, скажите я пойму ![]() Кстати вот картинка открытого в спец ГУИ программе записанных данных и вот как эти данные хранятся: Compound {x = 64-bit floating-point, name = String, length = variable, padding = H5T_STR_NULLTERM, cset = H5T_CSET_UTF8, family = String, length = variable, padding = H5T_STR_NULLTERM, cset = H5T_CSET_UTF8}->/CT1Извиняюсь, последние Ваши дополнения еще не просмотрел, сейчас на пару часов должен отойти
0
|
||||||||
|
|
|
| 22.12.2021, 19:56 | |
|
Поясните, что все ответы поехали в область каких-то безумных указателей и кастов?
Написать для каждой структуры конструктор копирования не судьба? Ну просто конструктор копирования из противоположного типа структуры.
0
|
|
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
|||
| 22.12.2021, 20:37 | |||
|
0
|
|||
|
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
|
|
| 22.12.2021, 20:39 [ТС] | |
|
Kuzia domovenok, дело в том что структуры произвольные могут быть и когда происходит чтение/запись то информации о структуре мало. Есть только офсеты членов и типы данных.
0
|
|
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
||
| 22.12.2021, 20:44 | ||
|
Только делать их надо правильно, пока что у ТС с этим проблема.
0
|
||
|
Вездепух
13239 / 6871 / 1827
Регистрация: 18.10.2014
Сообщений: 17,417
|
||||
| 22.12.2021, 21:07 | ||||
|
0
|
||||
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
|||||||||||||||||||
| 22.12.2021, 23:10 | |||||||||||||||||||
|
Какой именно offset у внутреннего указателя - неизвестно. В разных версиях стандартной библиотеки его расположение может отличаться. Плюс всякие приемы, вроде SSO. В старых версиях возможен COW. В самом лучшем случае записываемый библиотекой указатель совпадет с указателем внутри layout`а std::string. Если size и capacity при этом окажутся нулями, то это наверное даже заработает. Однако для этого нет абсолютно никаких гарантий. В общем, разве что вы намеренно хотите написать такой код, который будет заведомо нестабильным и кривым, зависящим от применяемых оптимизаций компилятора, его версии и версии стандартной библиотеки. Иначе этому нет никаких оправданий. Но вот дальше уже все не то. Как уже было сказано, объекта std::string у вас нет. У вас там Жук в коже от std::string. Значит никакого присваивания вы сделать не сможете. Внутренние данные std::string, - capacity, size не были правильно инициализированы, а значит оператор присваивания, который их использует, не будет правильно работать. Это как минимум. Я уже молчу о том, что в С++ в принципе не является легальным работать с нетривиальными объектами без их корректной инициализации. Т.е. даже если бы ваш сишный код каким-то чудом записал в size и capacity релевантные данные, то юзать оператор присваивания вы все равно не имеете права, потому что не соблюдено формальное требование инициализации объекта именно средствами С++, то бишь конструктором.std::string тут два.Однако в данном случае единственно верный способ - это использовать placement new. Мой пример из поста выше: Кликните здесь для просмотра всего текста
Это при условии, что память выделяется "сырая", без инициализации. Если же, как сделали вы, память выделяется вектором, то для всех нетривиальных полей нужно сначала позвать деструкторы явно. Кликните здесь для просмотра всего текста
Добавлено через 4 минуты Пример работы: https://rextester.com/CHWP34845 Добавлено через 5 минут Более корректный вариант: https://rextester.com/UFUH93694 Кликните здесь для просмотра всего текста
Добавлено через 4 минуты /// Лучше написать специальный класс буфера, который и использовать для записи. Например на основе std::aligned_storage. Исключим по крайней мере возню с деструкторами.
1
|
|||||||||||||||||||
|
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
|
||||||||||
| 23.12.2021, 04:45 [ТС] | ||||||||||
|
DrOffset, спасибо большое за разъяснения.
Почти все из того что вы написали до меня дошло. Сейчас обращаюсь к вашему последнему посту:
std::vector<CppStruct> использовать custom_buffer<CppStruct>? Если да, то для меня это не очень хорошо
0
|
||||||||||
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
||||
| 23.12.2021, 09:23 | ||||
|
Если в памяти есть объекты, то такая запись приведет к их порче. Поэтому деструктор мы вызвали именно для того, чтобы передать сишной библиотеке память, в которой нет объектов. Пусть она пишет в нее что хочет, потом мы получим эти данные и сделаем через placement new в этой же памяти новый объект, восстановим консистентность.
1
|
||||
|
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
|
|||
| 23.12.2021, 17:34 [ТС] | |||
|
DrOffset,
Для информации: в моем случае есть С библиотека HDF5, я пишу С++ врэппер (не с нуля, частично переделываю уже имеющийся), когда юзер подает вектор для чтения в С++ врэппер, я смотрю какого размера должен быть вектор (исходя из размера хранящихся на диске данных), делаю resize, а уже потом передаю буффер ( vec.data() ) в С библиотеку.
0
|
|||
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
|
| 23.12.2021, 18:59 | |
|
1
|
|
| 23.12.2021, 18:59 | |
|
Копировать байты из массива char в int C++ структуры. Копировать
Как копировать отдельные элементы из string в const char по C++ 98? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version
1. 2003 - 06 - Designing Virtual Worlds (1st Edition)
Автор: Richard A. Bartle | Объем: 768 стр.
Ссылки: Amazon
. . .
|
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
|
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы.
Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
|
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version
Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
|
|
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров".
Задача:
Запрет инициалов.
Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
|
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . .
Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
|
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг.
Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует.
В процессе разработки. . .
|
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
|