GCC - identifying elements at specific offsets

Is there a way in gcc where I could define a structure with a specific member at a specific offset?

I want to define the structure as follows:

struct { .offset(0xDC) //or something equivalent int bar; } foo; 

and then the following statement:

 int a = foo.bar 

will be identical to the statement:

 int a = *(int*)((char*)&foo + 0xDC); 

* UPDATE *

Some prerequisites: I want to access the elements in the exported structure that does not have the correct definition, it has many members, and I take care of only a few of them, and their offset (determination of the initial structure) is slightly different on each target platform (I need compile my code for several different platforms)

I considered the add-on option mentioned in the comments here, but it requires me to do some annoying calculations every time I want to add a member. eg:

 strcut { .offset(0xDC) int bar; .offset(0xF4) int moo; }foo; 

simpler:

 struct __attribute__ ((__packed__)) struct { char pad1[0xD8]; int bar; char pad2[0x18]; int moo; }foo; 

and that, without taking into account the fact that sizeof (int) can change from platform to platform

+8
c ++ c gcc
source share
6 answers

You should look at __attribute__ ((__packed__)) .

In your case, you should write:

 struct __attribute__ ((__packed__)) { char unused[0xDC]; int bar; } foo; 

If you could explain what you are trying to do, there might be other, perhaps more elegant, solutions.

+9
source share

You can always put it in bytes and make sure gcc does not align its structures (as this may reset offsets). In this case, you will need a member of type char pad_bytes[num_pad_bytes]; . Although there is reason to really do it? You can always calculate the offset of a member of the structure by doing some pointer arithmetic. Note: you can use the uint8_t type for the pad instead of char, as some compilers can actually cast char (which is usually a byte) on the size of the word.

Calculating an offset is as simple as

 size_t offset = (size_t)&((struct_type *)0)->member); 

All this just returns a pointer to where the member will be in struct_type if the structure was at 0x00 in memory (which will never happen), but since we use 0 as the base, then the offset is just a link, the returned operator and.

+2
source share

I considered the add-on option mentioned in the comments here, but it requires me to do some annoying calculations every time I want to add a member.

As for annoying calculations, you can simply generate a declaration of your structure using your preferred scripting language:

 struct = { 0xdc : (4, 'int bar'), 0xf4 : (4, 'int moo') } def print_struct_decl (name, decl): print "struct __attribute__ ((packed)) %s {" % name off = 0 i = 0; for o in sorted (decl.keys()): print "\tchar pad%d [%d];" % (i, o - off) i = i + 1 off = off + o + decl[o][0] print "\t%s;" % decl[o][1] print "};" print_struct_decl ("whatever", struct) 

Outputs:

 struct __attribute__ ((packed)) whatever { char pad0 [220]; int bar; char pad1 [20]; int moo; }; 
+2
source share

Solution using additions and combining as suggested in other answers:

 #include <stdio.h> #define OFF_STRUCT(name, members) union { members } name #define OFF_MEMB(offset, member) \ struct __attribute__ ((__packed__)) { \ char pad[offset]; \ member; \ } int main(int argc, char *argv[]) { OFF_STRUCT(foo, OFF_MEMB(0xD8, int bar); OFF_MEMB(0x18, double moo); OFF_MEMB(0x1, int bee); ); printf("offset: 0x%x 0x%x 0x%x\n", (void*)&foo.bar - (void*)&foo, (void*)&foo.moo - (void*)&foo, (void*)&foo.bee - (void*)&foo ); } 

Output:

 offset: 0xd8 0x18 0x1 
+2
source share

I would write a class that wraps a pointer:

 class whateverPtr { unsigned char *p; public: whateverPtr(void *p) : p(reinterpret_cast<unsigned char *>(p) { } uint32_t getBar() const { return read_uint32(0xdc); } private: uint32_t read_uint32(unsigned int offset) { return p[offset] | (p[offset + 1] << 8) | (p[offset + 2] << 16) | (p[offset + 3] << 24); } }; 

It is fully portable and will work, as expected, on bigendian architecture. Signed integers are a bit more complicated as you need to get the right encoding.

+1
source share

I do not propose to do this; Structures are not intended for this kind of data manipulation. If you need to change data in a specific place, use a correctly typed pointer to make changes in this way. Adding structures to the mix simply adds complexity without any benefits.

0
source share

All Articles