4

Suppose I have the following structure (in C):

struct my_struct {
  int foo;
  float bar;
  char *baz;
};

If I now have a variable, say

struct my_struct a_struct;

How can I find out how the fields of that structure are going to be laid out in memory? In other words, I need to know what the address of a_struct.foo, of a_struct.bar and a_struct.baz are going to be. And I cannot do that programatically, because I am actually cross-compiling to another platform.

CLARIFICATION

Thanks the answers so far, but I cannot do this programatically (i.e. with the offsetof macro, or with a small test program) because I am cross-compiling and I need to know how the fields are going to be aligned on the target platform. I know this is implementation-dependent, that's the whole point of my question. I am using GCC to compile, targeting an ARM architecture.

What I need in the end is to be able to dump the memory from the target platform and parse it with other tools, such as Python's struct library. But for that I need to know how the fields were laid out.

lindelof
  • 34,556
  • 31
  • 99
  • 140
  • 3
    You could use the `offsetof` macro to find the offset of the field. Is that what you're looking for? – Jeff Mercado Mar 20 '12 at 03:11
  • 1
    I would generally discourage an attempt to find out how a struct is laid out in memory. There are some legitimate use cases (e.g. malloc or an operating system kernel), but in general if you care about how a struct is laid out in memory you should use your compiler's options (in GCC you can try `__attribute__((packed))`) to ensure that the struct is laid out the same on every system. If you want this to be cross-compiler as well as cross-platform, you will probably have to use a bunch of `#if` blocks to end up with code that looks pretty messy. – Adam Mihalcin Mar 20 '12 at 03:18
  • 1
    @JeffMercado No, but +1 for telling me about the `offsetof` macro :-) – lindelof Mar 20 '12 at 03:42
  • 1
    You might be able to persuade your compiler to produce some layout information; you'd have to poke through its docs to see. However I don't quite understand why you dismiss offsetof or a test program just because you're cross-compiling. What's stopping you compiling the program and running it on your target architecture? Or since you apparently have the capability to dump the memory of your target, write a program which creates a few instances of your struct with known content - something like 0xdeadbeef in foo - then dump the memory and deduce from there. – Nigel Harper Mar 20 '12 at 10:10
  • You just saved me from typing the exact same question (only with a different embedded architecture). I kinda hoped that the `objdump` tool or something similar, or even the compiler (`gcc`) itself would be able to do that but none of the answers support that. My solution was to write a small program with the type declaration and using a bunch offsetof() prints to print the different field's offset (that, of course, assumes that you have a standard I/O capability in your embedded platform). Alternatively the offsets can be stored in an array where you have access from your host to read them. – ysap Sep 03 '12 at 20:27
  • @yasp you don't really have to run it. You can put the offsets into a global array. And then `objdump` tool would show you all the offsets. The I/O capabilities of the platform won't hinder you. – Ajay Brahmakshatriya Aug 17 '17 at 03:12

4 Answers4

4

In general, this is implementation specific. It depends on things like the compiler, compiler settings, the platform you are compiling on, word-size, etc. Here's a previous SO thread on the topic: C struct memory layout?

If you are cross-compiling, I'd imagine the specific layout will be different depending on which platform you compile for. I'd consult references for your compiler and platform.

Community
  • 1
  • 1
Guni
  • 41
  • 1
2

There's a program called pahole (Poke-A-Hole) in the dwarves package that will produce a report showing the structures of your program along with markers showing where and how large padding is.

OmegaNerd
  • 96
  • 3
0

One hacky way to see the memory view of what's inside it would be to cast a struct pointer to a char pointer, then print out all the chars, something like:

struct my_struct s;
s.foo = MAX_INT;
s.bar = 1.0;
s.baz = "hello";

for (int i = 0; i < sizeof(s); i++) {
  char *c = ((char*)&s) + i;
  printf("byte %d: 0x%02x\n", i, *c);
}

That doesn't explicitly show you the boundaries, you'd have to infer that from the dump.

Comments made by others about packing still apply; you'll also want to use explicitly sized types like uint32 instead of unsigned int 

Mohd Shahril
  • 2,257
  • 5
  • 25
  • 30
blueshift
  • 6,742
  • 2
  • 39
  • 63
0

I think you have two options.

The first one is to use __attribute__((packed)) after the struct declaration. This will ensure that each member will be allocated exactly the amount of memory that its type requires.

The other one is to examine your structure and use the alignment rules (n-byte basic type variable has to be n-byte aligned) to figure out the layout.

In your example, in either case each member variable will take 4 bytes and the structure will occupe 12 bytes in memory.

George Skoptsov
  • 3,831
  • 1
  • 26
  • 44