Сохранение типа данных в C

#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:

  1. Используйте «структуру»
  2. (необязательно) используйте специфичную для компилятора директиву «pack», чтобы гарантировать, что компилятор не «заполняет» какие-либо поля.
  3. (необязательно) используйте «memset» (или эквивалент) для обнуления блока
  4. Копирование данных по одному полю за раз

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);
}