#c #types #storage
#c #типы #Хранение
Вопрос:
Я не могу найти в сети ничего, что указывало бы, как поместить тип данных в предварительно выделенный блок памяти. Я ненавижу сам управлять памятью, но в этом случае я должен.
У меня есть блок памяти длиной 10 байт. (Мое приложение 64-битное, использующее Visual C.) То, что я хочу иметь возможность сделать, это поместить 1 unsigned int в байты 0-3, символ в [4] и символ в [5], а другой unsigned int в [6-9] .
Я уже пробовал ssprintf.
Итак, я пытаюсь найти способ 1) сохранить его в этом блоке памяти и 2) извлечь его.
Комментарии:
1. Вы сделали
struct
? Можете ли вы показать нам, что вы пробовали?2. Скорее всего, вам нужна структура: en.wikipedia.org/wiki/Struct_(C_programming_language)
3. Я реализовал его как структуру. Проблемы, с которыми я сталкиваюсь, заключаются в том, что у меня ОГРОМНОЕ количество данных, которые я не могу позволить себе читать / записывать на диск, и я многопоточен, и каждые 1 секунду все эти данные необходимо пересчитывать. Слишком много деталей, чтобы вдаваться в подробности, но это дает вам представление.
Ответ №1:
IMO, хороший способ добиться этого — определить структуру, содержащую описанные вами данные:
#pragma pack(1)
struct complex {
uint32_t a; // 4 bytes
char b[2]; // 2 bytes (without paddding)
uint32_t c; // 4 bytes
};
Затем вы можете просто заполнить свои данные:
struct complex var;
var.a = 10;
var.b[0] = 'x';
var.b[1] = 'y';
var.c = 20;
Обратите #pragma pack(1)
внимание, что директива указывает компилятору использовать выравнивание в 1 байт. Если вы не знаете, что это значит, вы можете прочитать о выравнивании структуры данных.
Ответ №2:
Если использование a struct
не является опцией, для загрузки данных в блок памяти должно работать следующее. Просто сделайте обратное, чтобы получить данные:
// char *mem = <10_bytes>;
unsigned int x = 54;
unsigned int y = 10;
memmove(mem, amp;x, 4);
memset(mem 4, 'A', 1);
memset(mem 5, 'B', 1);
memmove(mem 6, amp;y, 4);
Комментарии:
1. Это лучшее решение. структуры могут содержать любое количество байтов заполнения, поэтому они не являются переносимыми и не гарантируют выделение памяти в смежных байтах.
Ответ №3:
Вы обрабатываете байты (и вы не храните типы, вы просто храните в них данные). Вы можете либо объявить a struct
для выполнения ваших требований, либо скопировать байты данных (например, с memcpy
помощью) в соответствующие места, например, что-то вроде
unsigned int lastint;
char* buf;
memcpy (amp;lastint, buf 6, sizeof(lastint));
Однако имейте в виду, что работа с такими низкоуровневыми двоичными данными делает эти данные и ваше приложение крайне непереносимыми (и хрупкими, поскольку они будут ломаться при развитии приложения). Существуют более «стандартные» двоичные форматы (например, XDR или ASN1).
Ответ №4:
- Используйте «структуру»
- (необязательно) используйте специфичную для компилятора директиву «pack», чтобы гарантировать, что компилятор не «заполняет» какие-либо поля.
- (необязательно) используйте «memset» (или эквивалент) для обнуления блока
- Копирование данных по одному полю за раз
PS: Microsoft MSVC и Gnu Gcc оба используют «#pragma pack (1)» для предотвращения заполнения.
Ответ №5:
Вы можете использовать эту структуру:
#pragma pack(1)
struct TData {
unsigned int a;
char c1;
char c2;
unsigned int b;
};
И затем, в вашей функции:
int f()
{
char buffer[10]; // your 10
struct TData *data = (struct TData*)buffer;
printf("a: %d b: %b c1: %c c2: %c", data->a, data->b, data->c1, data->c2);
}