PaeneInsula
PaeneInsula

Reputation: 2100

Storing data type in C

I can't find anything on the net that tells how to put a data type into a pre-allocated block of memory. I hate doing memory management myself, but in this case I must.

I have a block of memory that is 10 bytes long. (My app is 64bit using Visual C.) What I want to be able to do is put 1 unsigned int into bytes 0-3, a char into [4] and char into [5], and another unsigned int into [6-9].

I tried ssprintf already.

So I'm trying to figure out a way to 1) store it into this block of memory and 2) retrieve it.

Upvotes: 0

Views: 391

Answers (5)

jweyrich
jweyrich

Reputation: 32240

IMO, a good way to accomplish that is by defining a struct containing the data you described:

#pragma pack(1)
struct complex {
    uint32_t a; // 4 bytes
    char b[2]; // 2 bytes (without paddding)
    uint32_t c; // 4 bytes
};

Then you can simply fill in your data:

struct complex var;
var.a = 10;
var.b[0] = 'x';
var.b[1] = 'y';
var.c = 20;

Note the #pragma pack(1) directive tells the compiler to use a 1-byte alignment. If you don't know what it means, you can read about data structure alignment.

Upvotes: 2

You are handling bytes (and you don't store types, you just store data in them). You can either declare a struct to fill your requirements, or copy the bytes of the data (e.g. with memcpy) into appropriate locations, e.g. something like

unsigned int lastint;
char* buf;
memcpy (&lastint, buf+6, sizeof(lastint));

However, be aware that dealing with such low-level binary data makes that data and your application extremely unportable (and brittle, since it will break when the application evolves). There exist more "standard" binary formats (e.g. XDR or ASN1).

Upvotes: 1

Pablo Santa Cruz
Pablo Santa Cruz

Reputation: 181280

You can use this struct:

#pragma pack(1)
struct TData {
    unsigned int a;
    char c1;
    char c2;
    unsigned int b; 
};

And then, on your function:

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

Upvotes: 0

user142162
user142162

Reputation:

If using a struct is not an option, the following should work for loading the data into the block of memory. Simply do the reverse to get the data out:

// char *mem = <10_bytes>;

unsigned int x = 54;
unsigned int y = 10;

memmove(mem, &x, 4);
memset(mem + 4, 'A', 1);
memset(mem + 5, 'B', 1);
memmove(mem + 6, &y, 4);

Upvotes: 1

paulsm4
paulsm4

Reputation: 121649

  1. Use a "struct"

  2. (optionally) use a compiler-specific "pack" directive to insure the compiler doesn't "pad" any fields.

  3. (optionally) use "memset" (or equivalent) to zero out the block

  4. Copy data a field at a time

PS: Microsoft MSVC and Gnu Gcc both use "#pragma pack(1)" to prevent padding.

Upvotes: 0

Related Questions