Structs and Alignment

  • Thread starter David Rasmussen
  • Start date
D

David Rasmussen

If I have

struct foo
{
char bar;
long baz;
};

on many platforms, padding and alignment is taking place to get baz to
start at an even address or an address that 4 divides. So baz is not
necessarily one byte (the size of char) into struct foo.

How can I know exactly how many bytes into struct foo baz is?

/David
 
S

Shan

David Rasmussen wrote
How can I know exactly how many bytes into struct foo baz is?

You can use sizeof() to know the size of the struct. However the
padding is implementation specific.
 
E

Emmanuel Delahaye

David Rasmussen wrote on 01/01/05 :
If I have

struct foo
{
char bar;
long baz;
};

on many platforms, padding and alignment is taking place to get baz to start
at an even address or an address that 4 divides. So baz is not necessarily
one byte (the size of char) into struct foo.

How can I know exactly how many bytes into struct foo baz is?

The sizeof operator is your friend (so is your C-book).

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.
 
P

Pierre Maurette

David Rasmussen a écrit :
If I have

struct foo
{
char bar;
long baz;
};

on many platforms, padding and alignment is taking place to get baz to
start at an even address or an address that 4 divides. So baz is not
necessarily one byte (the size of char) into struct foo.
"on my platform", you can try to bet on:
- no head padding, &struct == &struct.firstfield (rule).
- each field aligned according the compiler options, maybe its own size.
- end padding, calculated for:
struct.firstfield correctly aligned.
array of structs without padding (rule).

All this recursively, of course.
How can I know exactly how many bytes into struct foo baz is?
maybe:
size_t pad = (char*)&foo.baz - &foo;

The result should be different if for example you change
long baz;
to
char baz;
 
D

David Rasmussen

Hmm. The FAQ, I see, gives this answer:

2.14: How can I determine the byte offset of a field within a
structure?

A: ANSI C defines the offsetof() macro in <stddef.h>, which lets
you compute the offset of field f in struct s as
offsetof(struct s, f). If for some reason you have to code this
sort of thing yourself, one possibility is

#define offsetof(type, f) ((size_t) \
((char *)&((type *)0)->f - (char *)(type *)0))

This implementation is not 100% portable; some compilers may
legitimately refuse to accept it.

References: ISO Sec. 7.1.6; Rationale Sec. 3.5.4.2; H&S
Sec. 11.1 pp. 292-3.

I guess that solves the problem.

/David
 
M

Michael Mair

David said:
If I have

struct foo
{
char bar;
long baz;
};

on many platforms, padding and alignment is taking place to get baz to
start at an even address or an address that 4 divides. So baz is not
necessarily one byte (the size of char) into struct foo.

How can I know exactly how many bytes into struct foo baz is?

/David

Use the offsetof macro from <stddef.h>:

#include <stddef.h>

struct foo
{
char bar;
long baz;
};

int main (void)
{
size_t baz_offset = offsetof(struct foo, baz);

return 0;
}

-Michael
 
M

Michael Mair

Pierre said:
David Rasmussen a écrit :


"on my platform", you can try to bet on:
- no head padding, &struct == &struct.firstfield (rule).
- each field aligned according the compiler options, maybe its own size.
- end padding, calculated for:
struct.firstfield correctly aligned.
Nope: it is calculated s.t. the structure member with the
strictest alignment requirements is correctly aligned in
an array of >=2 elements of type struct foo.
array of structs without padding (rule).
Yep.

Note: In C99, structures with flexible array members cannot
build up arrays.

All this recursively, of course.


maybe:
size_t pad = (char*)&foo.baz - &foo;

Non-portable. The offset can be calculated using the
offsetof macro.
The result should be different if for example you change
long baz;
to
char baz;

s/should be/is probably/

Cheers
Michael
 
E

Emmanuel Delahaye

(supersedes <[email protected]>)

David Rasmussen wrote on 01/01/05 :
If I have

struct foo
{
char bar;
long baz;
};

on many platforms, padding and alignment is taking place to get baz to
start at an even address or an address that 4 divides. So baz is not
necessarily one byte (the size of char) into struct foo.

How can I know exactly how many bytes into struct foo baz is?

Size : The sizeof operator is your friend (so is your C-book).
Offset : Use the offsetof() macro.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
M

Mike Wahler

David Rasmussen said:
If I have

struct foo
{
char bar;
long baz;
};

on many platforms, padding and alignment is taking place to get baz to
start at an even address or an address that 4 divides. So baz is not
necessarily one byte (the size of char) into struct foo.

How can I know exactly how many bytes into struct foo baz is?

Others have already pointed out 'offsetof'. An alternative is
to create a 'dummy' object and do the computation yourself:

struct foo f;
ptrdiff_t ofs = &f.baz - &f;

-Mike
 
A

Alex Fraser

Mike Wahler said:
Others have already pointed out 'offsetof'. An alternative is
to create a 'dummy' object and do the computation yourself:

struct foo f;
ptrdiff_t ofs = &f.baz - &f;

ptrdiff_t ofs = (char *)&f.baz - (char *)&f;

Alex
 
J

Jack Klein

David Rasmussen wrote on 01/01/05 :

The sizeof operator is your friend (so is your C-book).

Indeed it is, but will not answer the OP's question. The offsetof()
macro will.
 
K

Keith Thompson

Mike Wahler said:
Others have already pointed out 'offsetof'. An alternative is
to create a 'dummy' object and do the computation yourself:

struct foo f;
ptrdiff_t ofs = &f.baz - &f;

Apart from the fact that the alternative won't work (&f.baz and &f are
of incompatible types), why do you need an alternative when the
language provides offsetof() for exactly this purpose?
 
M

Mike Wahler

Keith Thompson said:
Apart from the fact that the alternative won't work (&f.baz and &f are
of incompatible types),

Yes, Alex pointed out my error there.
why do you need an alternative when the
language provides offsetof() for exactly this purpose?

No, an alternative is not needed, but it might be wanted ... :)

-Mike
 
Y

Yan

Under FreeBSD 5.3, the macro is defined as follows:

#define __offsetof(type, field) ((size_t)(&((type *)0)->field))
 
M

Mike Wahler

Yan said:
Under FreeBSD 5.3, the macro is defined as follows:

#define __offsetof(type, field) ((size_t)(&((type *)0)->field))

The standard macro does not contain any underscores
in its name. Also note that the above construct
is undefined (due to the dereference of a null pointer)
when part of a C program, but an implementation is free
to implement 'offsetof' in any way appropriate to the
target platform.

BTW please do not top-post. Thank you.

-Mike
 
M

Mike Wahler

Keith Thompson said:
Seriously, why?

Your original "why" was part of "why do you need an alternative..."
I already admitted that you don't. Do you mean "why might an
alternative be wanted?". I don't really have a very serious
answer to that, only perhaps 'for fun' or 'to help understand
(via pure language constructs) how things are aligned in a struct.'
Another (I suppose unlikely) scenario is if your implementation's
'offsetof' macro is broken.

-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top