Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.59/17: Рейтинг темы: голосов - 17, средняя оценка - 4.59
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491

Копировать char * в член неизвестной структуры

20.12.2021, 18:24. Показов 3789. Ответов 30
Метки с++ (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер,

Допустим есть две структуры:
C++
1
2
3
4
5
6
7
8
9
10
11
typedef struct CT1 {
    double x;
    std::string name;
    std::string family;
} CT1;
 
typedef struct CT2 {
    double x;
    char * name;
    char * family;
} CT2;
CT2::name и CT2::family надо скопировать в CT1::name и CT1::family соответственно.
Сложность в том, что предполагается что CT1 неизвестная структура (в дальнейшем так будет).
О структуре CT1 известно только сколько в ней членов, тип каждого члена и оффсеты до каждого члена (offsetof(CT1, x), offsetof(CT1, name), offsetof(CT1, family)). В дальнейшем мне надо будет структуру CT2 скопировать в CT1 при этом скопировать данные из char * в std::string.

Не знаю решаема ли задача, но я для начала я хочу просто скопировать содержимое CT2.name в CT1.name используя оффсеты:
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
47
48
49
50
51
52
#include <string>
#include <cstring>
#include <iostream>
 
 
typedef struct CT1 {
    double x;
    std::string name;
    std::string family;
} CT1;
 
typedef struct CT2 {
    double x;
    char * name;
    char * family;
} CT2;
 
int main (void)
{
    CT1 ct1;
    CT2 ct2;
    ct2.x = 10;
    ct2.name = new char[sizeof "Tiger"];
    std::strcpy(ct2.name, "Tiger");
    ct2.family = new char[sizeof "Woods"];
    std::strcpy(ct2.family, "Woods");
 
    std::string tmp(ct2.name);
 
    ct1.name.resize(tmp.size());
    memcpy(&ct1+offsetof(CT1, name), tmp.c_str(), sizeof(tmp));
    // memcpy(&ct1.name, &tmp, sizeof(tmp));
 
    std::cout << "ct1.x: " << ct1.x << std::endl;
    std::cout << "ct1.name: " << ct1.name << std::endl;
    std::cout << "ct1.family: " << ct1.family << std::endl;
 
    std::cout << "strlen(ct2.name): " << strlen(ct2.name) << std::endl;
    std::cout << "sizeof(tmp): " << sizeof(tmp) << std::endl;
 
    std::cout << "offsetof(CT1, x): " << offsetof(CT1, x) << std::endl;
    std::cout << "offsetof(CT1, name): " << offsetof(CT1, name) << std::endl;
    std::cout << "offsetof(CT1, family): " << offsetof(CT1, family) << std::endl;
 
    std::cout << "offsetof(CT2, x): " << offsetof(CT2, x) << std::endl;
    std::cout << "offsetof(CT2, name): " << offsetof(CT2, name) << std::endl;
    std::cout << "offsetof(CT2, family): " << offsetof(CT2, family) << std::endl;
 
    delete[] ct2.name;
    delete[] ct2.family;
    return 0;
}
Но в результате ct1.name пустой:
  • ct1.x: 3.16202e-321
  • ct1.name:
  • ct1.family:
  • strlen(ct2.name): 5
  • sizeof(tmp): 32
  • offsetof(CT1, x): 0
  • offsetof(CT1, name): 8
  • offsetof(CT1, family): 40
  • offsetof(CT2, x): 0
  • offsetof(CT2, name): 8
  • offsetof(CT2, family): 16
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.12.2021, 18:24
Ответы с готовыми решениями:

Копировать пустую строку в const char* Конструктор структуры (класса)
Я думал, что это копирует в ch символ конца строки char *ch=new char; strcpy(ch,&quot;&quot;); delete ch; В обычном случае оно так и...

Прочитать строку из файла неизвестной структуры
Всем доброго времени суток! Имеется файл, созданный специальной программой по своим неизвестным правилам. В блокноте открывается....

Обработать входящий JSON неизвестной структуры
Здравствуйте. Нужна помощь с обработкой входящего JSON-на. И так: 1) Сторонний клиент отправляет на мой веб-сервис webhook...

30
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
22.12.2021, 19:42  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
Посмотрите на строки 60 и 61 в вашем коде. В 60 строке выинтерпретируете string из структуры как char*, а затем этот char* присваиваете этому же string. Это полная фигня, мягко говоря.
У меня есть пробелы в данной области, поэтому попробую изъяснить свою логику, а вам если нетрудно прокомментируйте пожалуйста

Я исхожу из следующих соображений:
в моем векторе есть баффер 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 *). На мой взгляд получается что то типо
C++
1
2
std::string name;
name = std::string(str_ptr);
В итоге 8-39 байты я интепретировал как std::string и поместил туда указатель на строку.

Цитата Сообщение от DrOffset Посмотреть сообщение
Kerim_Geophysic, Попробуйте понять, что Сишная библиотека не сможет правильно записать в такую структуру и просто похерит объекты std::string, после этого любое обращение к ним будет являться UB.
Почему? Ведь в этой библиотеке есть возможность указать количество байтов на каждый член структуры. В итоге размер записанного объекта соответствует sizeof(CT1).

Если мой тупизм зашкаливает, скажите я пойму

Кстати вот картинка открытого в спец ГУИ программе записанных данных и вот как эти данные хранятся:
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


Извиняюсь, последние Ваши дополнения еще не просмотрел, сейчас на пару часов должен отойти
Миниатюры
Копировать char * в член неизвестной структуры  
0
 Аватар для Kuzia domovenok
4268 / 3328 / 926
Регистрация: 25.03.2012
Сообщений: 12,545
Записей в блоге: 1
22.12.2021, 19:56
Поясните, что все ответы поехали в область каких-то безумных указателей и кастов?
Написать для каждой структуры конструктор копирования не судьба?
Ну просто конструктор копирования из противоположного типа структуры.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
22.12.2021, 20:37
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Почему?
Выше дал пример.

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Ведь в этой библиотеке есть возможность указать количество байтов на каждый член структуры. В итоге размер записанного объекта соответствует sizeof(CT1).
Этого не достаточно. Объекты в С++ должны быть правильно инициализированы. Для std::string это делает конструктор. Сишный код ничего не знает ни про std::string, ни про его конструкторы, поэтому он просто фигачит в переданную по void* память указатели на char* (примерно так, как это показано в моем примере). Если память, переданная по void*, уже изначально содержала корректные С++ объекты, то подобная манипуляция испортит их. Последующие действия с этими объектами будут некорректны. Т.к. std::string нетривиальный объект, то для него в конце жизни также будут вызваны деструкторы, что также является действием над объектом. Т.е. тут мы сами загнали себя в угол. Программа просто не сможет нормально работать.
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
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Поясните, что все ответы поехали в область каких-то безумных указателей и кастов?
Так это условие ТС. У него сторонняя библиотека засовывает в переданную память данные в соответствии с предварительно заданной "разметкой" в виде оффсетов. Теперь ТС хочет взять эти данные и поместить их в нормальную структуру на С++. Идея в том, чтобы написать обобщенный код, который будет любой набор данных от библиотеки засовывать в любую эквивалентную структуру на С++. Тут без без безумных кастов, по крайней мере применительно к данным от библиотеки, никак не обойтись.
Только делать их надо правильно, пока что у ТС с этим проблема.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13239 / 6871 / 1827
Регистрация: 18.10.2014
Сообщений: 17,417
22.12.2021, 21:07
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Поясните, что все ответы поехали в область каких-то безумных указателей и кастов?
Вы, может, почитайте тему сначала, чтобы разобраться о чем идет речь. Вроде все достаточно понятно объяснено.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Написать для каждой структуры конструктор копирования не судьба?
???

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ну просто конструктор копирования из противоположного типа структуры.
"Конструктор копирования из противоположного типа структуры" не называется "конструктором копирования".
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
22.12.2021, 23:10
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Насколько я знаю, std::string хранит в себе такой же указатель на массив как и char * и мне нужно правильно распорядиться этими 32 байтами.
Вы не можете закладываться на внутреннее устройство string.
Какой именно offset у внутреннего указателя - неизвестно. В разных версиях стандартной библиотеки его расположение может отличаться. Плюс всякие приемы, вроде SSO. В старых версиях возможен COW.
В самом лучшем случае записываемый библиотекой указатель совпадет с указателем внутри layout`а std::string. Если size и capacity при этом окажутся нулями, то это наверное даже заработает. Однако для этого нет абсолютно никаких гарантий.
В общем, разве что вы намеренно хотите написать такой код, который будет заведомо нестабильным и кривым, зависящим от применяемых оптимизаций компилятора, его версии и версии стандартной библиотеки. Иначе этому нет никаких оправданий.

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Строчка кода 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 *).
Вы скопировали нечто, что вы считаете должно быть указателем. В принципе это возможно так и есть.
Но вот дальше уже все не то.
Как уже было сказано, объекта std::string у вас нет. У вас там Жук в коже от std::string. Значит никакого присваивания вы сделать не сможете. Внутренние данные std::string, - capacity, size не были правильно инициализированы, а значит оператор присваивания, который их использует, не будет правильно работать. Это как минимум. Я уже молчу о том, что в С++ в принципе не является легальным работать с нетривиальными объектами без их корректной инициализации. Т.е. даже если бы ваш сишный код каким-то чудом записал в size и capacity релевантные данные, то юзать оператор присваивания вы все равно не имеете права, потому что не соблюдено формальное требование инициализации объекта именно средствами С++, то бишь конструктором.

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
На мой взгляд получается что то типо
C++
1
2
std::string name;
name = std::string(str_ptr);
В итоге 8-39 байты я интепретировал как std::string и поместил туда указатель на строку.
Если именно так сделать, то у вас гораздо больше шансов на успех, чем то, что выше сделали вы. Потому что объектов std::string тут два.
Однако в данном случае единственно верный способ - это использовать placement new.
Мой пример из поста выше:
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <cstring>
#include <vector>
#include <string>
 
struct CppStruct {
    int a;
    std::string b;
    std::string c;
};
 
// Симуляция поведения сишной библиотеки
void c_api_data(void** data) {
    
    void * raw = malloc(sizeof(CppStruct));
    if(raw) {
        *data = raw;
        char * p = (char*)raw;
 
        *(int *)  (p + offsetof(CppStruct, a)) = 42;
        *(char **)(p + offsetof(CppStruct, b)) = strdup("hello world!"); 
        *(char **)(p + offsetof(CppStruct, c)) = strdup("test!");
    }
}
 
int main()
{
    CppStruct * p1 = NULL;
    c_api_data((void **)&p1);
    
    char *str_ptrb;
    std::memcpy(&str_ptrb, &p1->b, sizeof(str_ptrb));
    ::new(&p1->b) std::string(str_ptrb);
    std::free(str_ptrb); // обязательно! об этом же написано в документации к вашей библиотеке
    
    char *str_ptrc;
    std::memcpy(&str_ptrc, &p1->c, sizeof(str_ptrc));
    ::new(&p1->c) std::string(str_ptrc);
    std::free(str_ptrc); // обязательно! об этом же написано в документации к вашей библиотеке    
    
    std::cout << p1->a << std::endl; 
    std::cout << p1->b << std::endl; 
    std::cout << p1->c << std::endl;    
}

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

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
47
48
49
50
#include <iostream>
#include <cstring>
#include <vector>
#include <string>
 
struct CppStruct {
    int a;
    std::string b;
    std::string c;
};
 
// Симуляция поведения сишной библиотеки
void c_api_data(void * raw) {
    
    if(raw) {
        char * p = (char*)raw;
 
        *(int *)  (p + offsetof(CppStruct, a)) = 42;
        *(char **)(p + offsetof(CppStruct, b)) = strdup("hello world!");
        *(char **)(p + offsetof(CppStruct, c)) = strdup("test!");
    }
}
 
int main()
{
    std::vector<CppStruct> out(1);
    
    using std::string;
    
    out[0].b.~string(); // обязательно ПЕРЕД вызовом сишной функции
    out[0].c.~string(); // обязательно ПЕРЕД вызовом сишной функции
    
    c_api_data(out.data());
    
    CppStruct * p1 = out.data();  // как именно получен указатель p1, через смещения, или как здесь, для этого примера не важно
    
    char *str_ptrb;
    std::memcpy(&str_ptrb, &p1->b, sizeof(str_ptrb)); // как именно получен указатель &p1->b, через смещения, или как здесь, для этого примера не важно
    ::new(&p1->b) std::string(str_ptrb);
    std::free(str_ptrb); // обязательно!
    
    char *str_ptrc;
    std::memcpy(&str_ptrc, &p1->c, sizeof(str_ptrc));  // как именно получен указатель &p1->c, через смещения, или как здесь, для этого примера не важно
    ::new(&p1->c) std::string(str_ptrc);
    std::free(str_ptrc); // обязательно!    
    
    std::cout << p1->a << std::endl; 
    std::cout << p1->b << std::endl; 
    std::cout << p1->c << std::endl;    
}


Добавлено через 4 минуты
Пример работы: https://rextester.com/CHWP34845

Добавлено через 5 минут
Более корректный вариант: https://rextester.com/UFUH93694
Кликните здесь для просмотра всего текста
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
47
48
49
#include <iostream>
#include <cstring>
#include <vector>
#include <string>
 
struct CppStruct {
    int a;
    std::string b;
    std::string c;
};
 
// Симуляция поведения сишной библиотеки
void c_api_data(void * raw) {
    
    if(raw) {
        char * p = (char*)raw;
 
        *(int *)  (p + offsetof(CppStruct, a)) = 42;
        *(char **)(p + offsetof(CppStruct, b)) = strdup("hello world!");
        *(char **)(p + offsetof(CppStruct, c)) = strdup("test!");
    }
}
 
int main()
{
    std::vector<CppStruct> out(1);
    
    out[0].~CppStruct(); // обязательно ПЕРЕД вызовом сишной функции
    
    c_api_data(out.data());
    
    CppStruct * p1 = out.data();  // как именно получен указатель, через смещения или как здесь для этого примера не важно
    
    char *str_ptrb;
    std::memcpy(&str_ptrb, &p1->b, sizeof(str_ptrb)); // как именно получен указатель, через смещения или как здесь для этого примера не важно
    char *str_ptrc;
    std::memcpy(&str_ptrc, &p1->c, sizeof(str_ptrc));  // как именно получен указатель, через смещения или как здесь для этого примера не важно
    int a;
    std::memcpy(&a, &p1->a, sizeof(a));
 
    CppStruct *p2 = ::new(p1) CppStruct{a, str_ptrb, str_ptrc};
    
    std::free(str_ptrb); // обязательно!
    std::free(str_ptrc); // обязательно!    
    
    std::cout << p1->a << std::endl; 
    std::cout << p1->b << std::endl; 
    std::cout << p1->c << std::endl;    
}

Добавлено через 4 минуты
///
Лучше написать специальный класс буфера, который и использовать для записи.
Например на основе std::aligned_storage.
Исключим по крайней мере возню с деструкторами.
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
23.12.2021, 04:45  [ТС]
DrOffset, спасибо большое за разъяснения.

Почти все из того что вы написали до меня дошло. Сейчас обращаюсь к вашему последнему посту:
Цитата Сообщение от DrOffset Посмотреть сообщение
Как уже было сказано, объекта std::string у вас нет. У вас там Жук в коже от std::string.
Не совсем понимаю почему вы это утверждаете. Возможно по следующей причине:
C++
1
2
3
CppStruct p1; // здесь мы инициализировали объект p1 (заняло 8+32+32 = 72 байт в программе) и соответственно его члены а и b
CppStruct* p2; // просто создали указатель (заняло 8 байт в программе) без инициализации и соответственно без его членов a и b
CppStruct* p3 = (CppStruct*) malloc(sizeof(CppStruct)); // тоже никакой инициализации не было хотя память выделена (заняло 8+8+32+32 = 80 байт в программе)
Правильно я понимаю, что мы можем создать указатель и даже выделить память под него, но при этом объект этого класса (и его члены) не будут инициализированы, и как раз член такого указателя я не могу реинтерпретировать в строку?

Цитата Сообщение от DrOffset Посмотреть сообщение
Однако в данном случае единственно верный способ - это использовать placement new.
Спасибо большое, это выглядит красивее и понятнее (не знал про это).

Цитата Сообщение от DrOffset Посмотреть сообщение
Это при условии, что память выделяется "сырая", без инициализации.
Если же, как сделали вы, память выделяется вектором, то для всех нетривиальных полей нужно сначала позвать деструкторы явно.
Можете пояснить, зачем явно вызывать деструкторы? Вроде ссылку нашел но не врубаюсь пока что

Цитата Сообщение от DrOffset Посмотреть сообщение
Лучше написать специальный класс буфера, который и использовать для записи.
Например на основе std::aligned_storage.
Исключим по крайней мере возню с деструкторами.
Вы имеете ввиду вместо std::vector<CppStruct> использовать custom_buffer<CppStruct>? Если да, то для меня это не очень хорошо
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
23.12.2021, 09:23
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
при этом объект этого класса (и его члены) не будут инициализированы, и как раз член такого указателя я не могу реинтерпретировать в строку?
Да.

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Можете пояснить, зачем явно вызывать деструкторы?
Затем, что Сишная библиотека в переданную память пишет свои данные.
Если в памяти есть объекты, то такая запись приведет к их порче.
Поэтому деструктор мы вызвали именно для того, чтобы передать сишной библиотеке память, в которой нет объектов.
Пусть она пишет в нее что хочет, потом мы получим эти данные и сделаем через placement new в этой же памяти новый объект, восстановим консистентность.

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Если да, то для меня это не очень хорошо
Чем именно?
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
23.12.2021, 17:34  [ТС]
DrOffset,
Цитата Сообщение от DrOffset Посмотреть сообщение
Затем, что Сишная библиотека в переданную память пишет свои данные.
Если в памяти есть объекты, то такая запись приведет к их порче.
Поэтому деструктор мы вызвали именно для того, чтобы передать сишной библиотеке память, в которой нет объектов.
Пусть она пишет в нее что хочет, потом мы получим эти данные и сделаем через placement new в этой же памяти новый объект, восстановим консистентность.
А если я перед тем, как передать в С библиотеку вектор для чтения данных делаю его ресайз? Надо ли явно вызывать деструктор?
Для информации: в моем случае есть С библиотека HDF5, я пишу С++ врэппер (не с нуля, частично переделываю уже имеющийся), когда юзер подает вектор для чтения в С++ врэппер, я смотрю какого размера должен быть вектор (исходя из размера хранящихся на диске данных), делаю resize, а уже потом передаю буффер ( vec.data() ) в С библиотеку.

Цитата Сообщение от DrOffset Посмотреть сообщение
Чем именно?
Да может быть нормально, надо будет пробовать
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
23.12.2021, 18:59
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
А если я перед тем, как передать в С библиотеку вектор для чтения данных делаю его ресайз? Надо ли явно вызывать деструктор?
Да, после resize, до передачи.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.12.2021, 18:59

Можно ли копировать из string в char?
Приветствую! У меня задание записать в переменную char *name несколько слов, но я видел методы только для string.Можно ли без бубна...

Копировать байты из массива char в int
Добрый день Какими стандартными функциями это можно реализовать? Например, я получаю ответ с сервера при помощи функции recv знаю, что в...

C++ структуры. Копировать
void zadanie12() { struct Univer{ char *fam; char *kaf; char *dol; double zar;}; Univer...

Копировать элемент массива String в массив char
Приветствую Вас, дорогие форумчане, помогите кто может в следующем вопросе, имеется массив String с одним элементом, размером более 800...

Как копировать отдельные элементы из string в const char по C++ 98?
в зависимости от выполнения условия нужно скопировать только нужные символы, чтобы потом преобразовать их к int через atoi. Подскажите...


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

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
Новые блоги и статьи
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
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(). Нажатие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru