devoured_elysium
asked on
I'd like to know how structs are stored in memory
Hello. I'd like to know how structs are stored in memory. For example, if i have the following struct:
struct A {
int _a;
int _b
}
will it be safe to assume that if an instance of struct A is allocated at memory offset 100, the variable _a will be stored at 100 and variable _b will be at 100 + sizeof(int) ?
struct A {
int _a;
int _b
}
will it be safe to assume that if an instance of struct A is allocated at memory offset 100, the variable _a will be stored at 100 and variable _b will be at 100 + sizeof(int) ?
>> the variable _a will be stored at 100
That is guaranteed, yes. The first struct field always starts at the start address of the struct.
>> variable _b will be at 100 + sizeof(int)
Since int is the standard type, this will be true on most platforms, but there's no guarantee. The compiler might add padding between struct fields if needed.
Note that padding can be added between the fields, and at the end of the struct. Usually padding is added to align the fields on word boundaries.
That is guaranteed, yes. The first struct field always starts at the start address of the struct.
>> variable _b will be at 100 + sizeof(int)
Since int is the standard type, this will be true on most platforms, but there's no guarantee. The compiler might add padding between struct fields if needed.
Note that padding can be added between the fields, and at the end of the struct. Usually padding is added to align the fields on word boundaries.
ASKER
If I know the struct declaration, am I able to read the values directly from memory? I mean, if I have a structure defined in project A which is like that one above, and I have one instance which I read from memory and send to another project(called project B), will I be able to just by pointer arithmetic read the contents of the struct, without ever defining it?
Thanks
Thanks
>> will I be able to just by pointer arithmetic read the contents of the struct, without ever defining it?
If you know which padding was added, and if the other platform uses the same data type sizes and definitions, then that should work yes.
But, I would suggest to use an encoding to transfer data between systems, and then decode it on the target system into its own struct.
If you know which padding was added, and if the other platform uses the same data type sizes and definitions, then that should work yes.
But, I would suggest to use an encoding to transfer data between systems, and then decode it on the target system into its own struct.
To do that, you'll have to know what the alignment is so that you know how much padding may be between the data items.
If the default alignment is a 32-bit boundary, note that defining and item as a char will cause the next item to move to the 32-bit boundary. If you declare consecutive items as *char*, it doesn't matter that it will fit, the second one will be moved to the next alignment boundary.
The only way to be sure how and where the item will align will be to control the alignment yourself (via compiler options or #pragma statements) or to compute them yourself. The code below should tell you what the alignment size is. Your only challenge beyond that is to note which items are larger than this and note that they will align on a multiple of this value.
Good Luck,
Kent
struct
{
a char;
b char;
} aligntest_t;
aligntest_t Test;
printf ("alignment is %d bytes\n", &Test.b - &Test.a);
Kent
ASKER
Hm, I still don't get one thing. The way Windows will pad the struct will be ALWAYS the same on the same computer, or will depend on how full the memory currently is, etc? If I see that windows will right now put the two ints together without padding them for an instance of my struct, is it correct to assume it will do the same for another 100?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The alignment is a compile time decision, controller by you (as compiler options) or the source code. The amount of memory available at run time has no bearing on alignment.
Kent
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
May I ask why you gave a B grade ? That usually means that something is missing in the answers and/or that something is still unclear. If that's the case, then please do not hesitate to ask for clarification where needed.
ASKER
I am sorry, I just gave points and skimmed through the page. If there's a way to still change it, I'll do it. Is there?
No worries. I just wanted to make sure that you got the help you needed.
For your information, here are a few FAQ entries that might interest you :
https://www.experts-exchange.com/help.jsp#hi403
For your information, here are a few FAQ entries that might interest you :
https://www.experts-exchange.com/help.jsp#hi403
Technically what you can assume is that
A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa.
But
There may be unnamed
padding within a structure object, but not at its beginning.
A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa.
But
There may be unnamed
padding within a structure object, but not at its beginning.
the standard header <stddef.h>.
defines
offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of
which is the offset in bytes, to the structure member (designated by member-designator),
from the beginning of its structure (designated by type). The type and member designator
shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an address constant. (If the
specified member is a bit-field, the behavior is undefined.)
defines
offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of
which is the offset in bytes, to the structure member (designated by member-designator),
from the beginning of its structure (designated by type). The type and member designator
shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an address constant. (If the
specified member is a bit-field, the behavior is undefined.)
For the most part, yes. There are often compiler options to regulate alignment that results in each item starting on a character, 16-bit, 32-bit, or 64-bit boundary. But the default alignment is usually in line with sizeof (int).
Good Luck,
Kent