Skip to main content
gamedev.net
🔒 Locked

memcpy offset for structures

Started by Hassanbasil 7 replies 3.5k views
Original Post
Hassanbasil
Hassanbasil
Hello everyone,

take a look at this code:
	struct mystruct	{		int x;		int y;	};	void* mem = malloc ( sizeof mystruct );	mystruct s;	s.x = 10;	s.y = 20;	memcpy ( mem, &s, sizeof mystruct );


now ptr has the values of 10 and 20, what if i want to change the 20 to 30, without changing the 10?

the place where memcpy is being called from does not know what is mystruct, but it knows it's size and the sizes of it's components, how can i use memcpy to change y?

something like memcpy ( mem + offset, value, sizeof (int) );
the_edd
the_edd
Quote:
Original post by Hassanbasil
Hello everyone,

take a look at this code:
*** Source Snippet Removed ***

now ptr has the values of 10 and 20, what if i want to change the 20 to 30, without changing the 10?

the place where memcpy is being called from does not know what is mystruct, but it knows it's size and the sizes of it's components, how can i use memcpy to change y?

something like memcpy ( mem + offset, value, sizeof (int) );


The question on everyone's lips is going to be "why don't you do it without using memcpy, as that's a hundred times easier?". i.e

mystruct *s2 = static_cast<mystruct *>(mem);s2->y = 30;


Otherwise, aren't you just asking how to get the address of the "y" member in a given instance of a struct? The answer to that is to use the address operator:

void *address_of_y = &instance.y// then you can memcpy like so:int i = 30;memcpy(address_of_y, &i, sizeof i);


But really, you should be avoiding memcpy as far as possible in C++, especially here where "traditional" assignment is entirely appropriate.
Decrius
Decrius
You could use struct packing, where no padding is used for data alignment etc (see your compilers manuals for the syntax for struct packing).

That way, you can simply add up the sizes of the members:
char *mem = (char *) malloc(sizeof(mystruct));*(mem + 0) = 5;            // first member (x)*(mem + sizeof(int)) = 10; // second member (y)


Or use memcpy in a similar fashion.

But I find the requirement slightly dubious...I'm sure there is a better way to solve the problem you are facing...

EDIT: or use the address operator yes indeed.
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Hassanbasil
Hassanbasil
Quote:
Original post by the_edd
Quote:
Original post by Hassanbasil
Hello everyone,

take a look at this code:
*** Source Snippet Removed ***

now ptr has the values of 10 and 20, what if i want to change the 20 to 30, without changing the 10?

the place where memcpy is being called from does not know what is mystruct, but it knows it's size and the sizes of it's components, how can i use memcpy to change y?

something like memcpy ( mem + offset, value, sizeof (int) );


The question on everyone's lips is going to be "why don't you do it without using memcpy, as that's a hundred times easier?". i.e

mystruct *s2 = static_cast<mystruct *>(mem);s2->y = 30;


Otherwise, aren't you just asking how to get the address of the "y" member in a given instance of a struct? The answer to that is to use the address operator:

void *address_of_y = &instance.y// then you can memcpy like so:int i = 30;memcpy(address_of_y, &i, sizeof i);


But really, you should be avoiding memcpy as far as possible in C++, especially here where "traditional" assignment is entirely appropriate.


As i said, the place where memcpy is being called from does not know what is mystruct, it only knows it's size and the sizes of it's members

Decrius that method worked, thanks alot!
swiftcoder
swiftcoder
Quote:
Original post by Hassanbasil
Decrius that method worked, thanks alot!
But don't rely on it working tomorrow! Compile your code for 64-bit, and it will break. Compile your code with a compiler that doesn't understand the packed attribute, and it will break. Look at the computer funny or sneeze, and it will break...

This sort of hackery is better left well enough alone - there are almost always better ways to accomplish the same thing.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
rip-off
rip-off
Quote:

As i said, the place where memcpy is being called from does not know what is mystruct, it only knows it's size and the sizes of it's members


Tell us more about this piece of code. There is probably a way of doing it better. That said, you should probably use something like offsetof, rather than hard-coding values for the offset and size of members (which can and probably will change).
Decrius
Decrius
Quote:
Original post by swiftcoder
Compile your code for 64-bit, and it will break.


Well, I do use the sizeof for the int, so that should be no problem.
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Hassanbasil
Hassanbasil
the thing is:

im working on direct3D 11 shaders, without the effect11 framework, when you load a shader, you can obtain a shader reflection, which has description for the shader and resources it use, so for example, you have in your shader code (a standalone file, not in cpp)

cbuffer cbPerObject{	float4x4 gWVP;	float4x4 gWorld;	float gAlpha;	float gClipAlpha;	bool gUsingTexture;	float4 gMaterial;	bool bSolid;};


now in the cpp code, shader reflection tells you that you have a buffer called cbPerObject, and it's size is x, the buffer has the variables blablabla and their sizes are blabla and the offset from the beginning is blabla, now to actually assign value to those variables from the cpp code, you need to pass a buffer containing the exact same info as the structure (cbuffer) above, yes it is possible to make a structure to match the cbuffer and pass it for the buffer, but since im creating an ENGINE, im not supposed to know what structures the user will use, thus i just have a void pointer allocating the same size as the cbuffer.
i can request a void pointer from the user that contains the full structure, but im also creating other ways of assigning the values, the most efficient way is to request a variable name and a void pointer containing the data to assign it to, so the function loops through the buffers, then loops through variables in each buffer searching for the specified name, once it finds it, it uses memcpy ( buffer + variableOffset, value, variableSize ), currently the buffer is a char*.

that's the whole idea, if you have a better way of doing this, please let me know

and by the way, what's with the 64 bit thing? why wouldn't it work?
swiftcoder
swiftcoder
Quote:
Original post by Hassanbasil
and by the way, what's with the 64 bit thing? why wouldn't it work?
As long as you use explicitly-sized types, and you use the compiler-specific attribute to cause the struct to be packed, then everything should be fine.

Since your struct is created by DirectX, I assume that they have taken care of those details for you - but you didn't mention that at the outset.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.