1
votes

Hello there and thank you with your help!

I am trying to make universal data buffer for multiple data type (char, int, float,...whatever) and I would like to know how access specific address with pointer to buffer and specific position.

Let me explain it on example:

1.) Let's say that I would like to save to buffer 4 variables (int, int, char, float)

2.) so, size of this buffer is: int size = sizeof(int)*2 + sizeof(char) + sizeof(float)

3.) so, buffer: void* buffer = malloc(size);

4.) Right now, I have allocate buffer and I would like to write some float variable to specific position - which is buffer + (sizeof(int)*2 + sizeof(char) ) right? How to do that and if is it possible...

I have solution that I will write data how they are specified and its working, but I would like to jump on what ever position (of course, when I know, where exactly (address) some variable is in buffer)

So something like that works to me:

int* val1 = (int*) buffer;
*val1 = 1;
buffer = val1+1; //move pointer behind first position (+ sizeof(int))
int* val2 = (int*) buffer;
*val2 = 2;
buffer = val2+1; //move pointer behind second position (+ sizeof(int))
char* val3 = (char*) buffer;
*val3 = 'a';
buffer = val+1; //move pointer behind third position (+ sizeof(char))
float* val4 = (float*) buffer;
*val4 = 11.4;

--> All data are saved in the buffer corectly

But I am more interesting, if is possible (and how) to jump and write first float on 4th position (dont forget that before is int, int, char)

Because I can't use something like:

float* val4 = (float*) buffer + 4; // value 4 has address buffer + sizeof(float)*4 and I need     address buffer + sizeof(int)*2 + sizeof(char)

Sorry for this slow explanation, but I wanna be sure, that it's really obvious what I need to solve. Thank you very much for your help!

p.s: I have in my head just one solution with (char*) buffer (because on every platform should be sizeof(char) == 1 ....but I am not sure, if this is really save option)

so after:

char* pointerOnVal4 = (char*) buffer + sizeof(int)*2 + sizeof(char);
float* val4 = (float*) pointerOnFloat;`
2
you are talking about manual memory management. what is the purpose of this kind of storage? wouldn't it be easier to have a dynamic data structure like linked list (or something directly addressable) that stores pointers castable to different data types? please elaborate.Pavel
Before you start putting serious work into this, you need to understand Data alignment. Every 16 bit type should be at a 16 bit boundary, and every 32 bit type should be at a 32 bit boundary… Look into memory packing algorithms.Jeffery Thomas
From what I can tell, you need either a struct or a union (or both). Don't hack about with bytes and pointers.The Paramagnetic Croissant
Listen to @JefferyThomas and @user3477950. What you are trying to do is a lot harder than the naive approach you are attempting for a variety of system-dependent reasons, and it is something the compiler will do for for free. Your code is trying to reinvent struct (or class), but by the looks of it, it appears that what you really need is provided by union. Read up on those features.Euro Micelli
Is there a question here, counselor?user3344003

2 Answers

0
votes

From the way you described the problem, you want:

struct Foo
{
    int a, b;
    char c;
    float f;
};

But if you really need to do it dynamically (I'm not sure why you would), you would write something like:

struct Type
{
    size_t align;
    size_t size;
};

struct Field
{
    Type *type;
    size_t offset;
};

class ObjectType
{
private:
    std::vector<Field> fields;
public:
    void add_field(Type *t)
    {
        size_t off = fields.empty() ? 0 : fields.back().offset + fields.back.type->size;
        if (off % t->align)
            off += t->align - off % t->align;
        fields.push_back({t, off});
    }
};

... and then use ObjectType on an array of uint8_t

Note that there is no general relation between the size and alignment of a type, except that size must be a multiple of align. For example, on some systems, long double has align 4 and size 12 (but only uses 10 bytes for significant data, and 2 bytes for padding).

That said, if you want this to be compatible between platforms (e.g. across the network, but also for 32-bit vs 64-bit code on the same host), you need to do a lot more than this.

0
votes

Like the above answer, stick to struct for this:

typedef struct Foo{
    int a;
    int b;
    char c;
    float f;
}Foo;

Foo *bar = new(struct Foo);
bar->a = 1;
bar->b = 2;
bar->c = 'a';
bar->f = 11.4;
delete(bar);