Structure padding.

A

Amarendra

Folks,

This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.

Thanks in advance.

Cheers,
Amar
 
A

Arthur J. O'Dwyer

This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ?

Obviously not. Any compiler is perfectly capable of padding
your structure to make it a multiple of 8 bytes, minus 1, and
there's nothing you can do about it, from the Standard's point
of view.
In practice, you'll probably be able to get away with a
system-specific solution such as

#define PAD_EIGHT(siz) ((siz) - (siz)/8*8)
struct half_foo {
int flag;
char keys[3][9];
};
typedef struct {
int flag;
char keys[3][9];
char padding[PAD_EIGHT(sizeof (struct half_foo))];
} foo;

or (even less portably but much clearer to the next guy)

typedef struct {
int flag;
char keys[3][9];
char padding[1]; /* Pad to a multiple of 8 bytes */
} foo;

In practice, of course, it doesn't matter at all what the size
of your structure is: let the computer worry about it. Most
compilers have some kind of "optimize for speed/space" flag
that will make your code run quickly no matter what the size of
some little structure is.

-Arthur
 
J

Jens.Toerring

Amarendra said:
This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...
I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;
I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.

That's something clc can't answer because there is no requirement
on how much padding a compiler is supposed to use by the C standard.
It obviously will differ between different architectures, but also
compilers and maybe even different compiler versions. The first
question that comes to mind is why you need the structures size to
be a multiple of 8?

<OT>
You could write a script that writes C programs that create structures
like the above with ever increasing lengths for the padding array and
which then write out the sizeof the structure. The script compiles
and runs these programs until the structures size is a multiple of 8
and you use that length of the padding array in the real program (maybe
by writing the value into an include file to be included by the real
program). Shouldn't be too hard to do with a reasonably short script.
</OT>
Regards, Jens
 
C

Chris Torek

This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? ...

The answer is no -- and yes.

There is no way to do it "in one pass", as it were, but you can
still do it by generating the declaration at runtime, then (after
this runtime has finished) use that declaration at a later
compile-time.

This does make some assumptions, such as "a later invocation of
the compiler will use the same layout as an earlier invocation of
the compiler" -- which should be true unless you wait too long (so
that the compiler has been replaced with a later version), or change
the set of flags you pass to the compiler. It also makes the build
process for your software (much) more complicated: instead of just
"compile all this C code", you have to do this, in sequence:

- compile C code to generate the structure
- run the program, putting the struct declaration into a file for
use in the next step
- compile the code that uses the newly-created declaration

It is not clear to me why you want an explicit "padding blob". In
my experience, most people who do that are trying to make the
internal C structure layout meet some external file format -- which
is often a mistake, as it is sometimes quite difficult to get an
internal data structure to match external constraints at all, and
often quite easy to make the input and output operations translate
between "external" and "internal" formats. The translation code
can either assume or force 8-bit "regular bytes" (octets) using "C
bytes" (unsigned char), which are usually exactly 8 bits, and are
never fewer than 8 bits. The "externalized" octets can be matched
to the desired layout completely portably.
 
T

Thomas Matthews

Amarendra said:
Folks,

This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.

Thanks in advance.

Cheers,
Amar

In these cases, I revert to assembly language. Many assembly
languages provide compiler directives to align data fields
to a given boundary. I then "export" the symbol and use
"extern" in the C language.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
A

Arthur J. O'Dwyer

Amarendra said:
I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.
<OT>
You could write a script that writes C programs that create structures
like the above with ever increasing lengths for the padding array and
which then write out the sizeof the structure. The script compiles
and runs these programs until the structures size is a multiple of 8
and you use that length of the padding array in the real program (maybe
by writing the value into an include file to be included by the real
program). Shouldn't be too hard to do with a reasonably short script.
</OT>

Hey, good idea! :)

#include <stdio.h>

#define PADSIZE(n) (sizeof(struct {int flag; char keys[9][3]; \
char pad[n];}))
#define PADOK(n) (PADSIZE(n)%8==0)
#define PAD (PADOK(1)? 1: PADOK(2)? 2: PADOK(3)? 3: PADOK(4)? 4: \
PADOK(5)? 5: PADOK(6)? 6: PADOK(7)? 7: PADOK(8)? 8: -1)

typedef struct {
int flag;
char keys[9][3];
char padding[PAD];
} foo;

(Naturally, the OP should not use this method. Nor should anyone else.)

-Arthur
 
E

Eric Sosman

Amarendra said:
Folks,

This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.

Others have pointed out that there's no completely
guaranteed solution (because the compiler may add more
padding bytes you have no control over). Others have
also offered some non-guaranteed solutions involving
macros and/or two passes. Here's a variation that
might be simpler, if you can tolerate having the padding
appear "after" the struct rather than inside it:

typedef union { /* not struct */
struct foo_data {
int flag;
char keys[3][9];
} payload;
char overlay[(sizeof(struct foo_data) + 7) / 8];
} foo;

A disadvantage is that you need to write things like
`fooptr->payload.flag' instead of `fooptr->flag'. And,
of course, the compiler might still decide to make the
union larger than you want, and this might destroy the
multiple-of-eight size.
 
D

Dan Pop

In said:
This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.

Yes. It's not strictly guaranteed to work (it will fail if the struct
needs to be aligned to multiples of something greater than 8 or that is
not a power of two) and, in theory, the compiler may add some padding of
its own at the end, but in practice you can calculate the padding if the
compiler is happy with the idea of the structure size being a multiple of
8. In the worst case you may have to add 8 bytes of padding, because
you can't have arrays of size 0. Needless to say, the padding may
differ between implementations (but this is transparent to the source
code).

There is more than way of doing it, but I prefer the one that completely
virtualises the struct definition, at the expense of declaring an
auxiliary structure, mirroring the real one, first:

fangorn:~/tmp 155> cat test.c
#include <stdio.h>
#include <assert.h>
#include <stddef.h>

#define ALIGN 8

struct foo_aux {
int flag;
char keys[3][9];
char padding;
};

struct foo {
int flag;
char keys[3][9];
char padding[ALIGN - offsetof(struct foo_aux, padding) % ALIGN];
};

int main()
{
assert(offsetof(struct foo_aux, padding) == offsetof(struct foo, padding));
assert(sizeof(struct foo) % ALIGN == 0);
printf("%d\n", (int)sizeof(struct foo));
return 0;
}
fangorn:~/tmp 156> gcc test.c
fangorn:~/tmp 157> ./a.out
32

The catch is that both struct definitions must be kept in sync, when
changes are made. This is actually tested by the first assert. If the
second assert fails, there is nothing you can do: the compiler is not
happy with a structure size that is a multiple of 8.

There is a way to automatically keep the two structures in sync, but I'm
not very fond of it: put the common part of the two declarations in a
separate file and include it. Change that file when you need to modify
the structure definition. It's a readability vs maintenability tradeoff.

fangorn:~/tmp 166> cat struct_foo.c
int flag;
char keys[3][9];
fangorn:~/tmp 167> cat test.c
#include <stdio.h>
#include <assert.h>
#include <stddef.h>

#define ALIGN 8

struct foo_aux {
#include "struct_foo.c"
char padding;
};

struct foo {
#include "struct_foo.c"
char padding[ALIGN - offsetof(struct foo_aux, padding) % ALIGN];
};

int main()
{
assert(sizeof(struct foo) % ALIGN == 0);
printf("%d\n", (int)sizeof(struct foo));
return 0;
}
fangorn:~/tmp 168> gcc test.c
fangorn:~/tmp 169> ./a.out
32

Dan
 
D

Dan Pop

In said:
Amarendra said:
This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...

I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;

I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.

Others have pointed out that there's no completely
guaranteed solution (because the compiler may add more
padding bytes you have no control over). Others have
also offered some non-guaranteed solutions involving
macros and/or two passes. Here's a variation that
might be simpler, if you can tolerate having the padding
appear "after" the struct rather than inside it:

typedef union { /* not struct */
struct foo_data {
int flag;
char keys[3][9];
} payload;
char overlay[(sizeof(struct foo_data) + 7) / 8];
} foo;

A disadvantage is that you need to write things like
`fooptr->payload.flag' instead of `fooptr->flag'.

Another "disadvantage" is that you're grossly miscalculating the size of
overlay, which is 8 times smaller than it should be! No point in
dividing by 8 if you don't multiply back by 8 ;-)

Dan
 
J

John Ilves

This seems to work for me (with gcc on linux):

#include <stdio.h>

struct foo
{
int flag : 4; /* force 32 bit */
char keys[3][9]; /* 3 * 9 == 27 */
int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */
};

int
main()
{
printf( "struct foo is %d bytes, and %s divisible by 8\n",
sizeof(struct foo),
sizeof(struct foo) % 8 ? "is not" : "is" );

return 0;
}

Hope it helps,
John

PS Nice email address. :)
 
A

Arthur J. O'Dwyer

This seems to work for me (with gcc on linux): [...]
struct foo
{
int flag : 4; /* force 32 bit */

s/32/4/ . (You wrote "4" in the code and "32" in the comment.)
char keys[3][9]; /* 3 * 9 == 27 */
int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */

But where's the missing dollar?

Of course, no matter how many bits you use in your struct, GCC will
generally pad it out to a decent multiple of 4 or 8 in any event.

Because it's annoying as hell.
Why not?
And don't top-post.

-Arthur
 
E

Eric Sosman

John said:
This seems to work for me (with gcc on linux):

#include <stdio.h>

struct foo
{
int flag : 4; /* force 32 bit */

ITYM "force 4 bit." Don't feel bad, though: everybody's
entitled to one silly mistake per thread (and I've already
claimed mine ...)
char keys[3][9]; /* 3 * 9 == 27 */
int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */

`_pad_' happens to be safe in this context, but would
be unsafe in most others. Stan Brown's list of identifiers
to avoid

http://www.oakroadsystems.com/tech/c-predef.htm

is still based on the older C89 Standard and has not been
updated for C99, but is still helpful.

Oh, and the `: 1' doesn't do what you seem to believe.
 
J

John Ilves

Eric said:
ITYM "force 4 bit." Don't feel bad, though: everybody's
entitled to one silly mistake per thread (and I've already
claimed mine ...)
Heh, oops. Specifying struct field lengths isn't something I've used
before, I've just heard about it. Obviously the 4 here should be a 32
and the 1 for _pad_ should be an 8 since field lengths are specified in
bits not bytes.
char keys[3][9]; /* 3 * 9 == 27 */
int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */


`_pad_' happens to be safe in this context, but would
be unsafe in most others. Stan Brown's list of identifiers
to avoid

http://www.oakroadsystems.com/tech/c-predef.htm

is still based on the older C89 Standard and has not been
updated for C99, but is still helpful.
I guess that wasn't a very good name. I just wanted to make it clear
that that field wasn't intended to be used.
Oh, and the `: 1' doesn't do what you seem to believe.
Like I said above, it should have been an 8. :-/
 
R

Ralmin

Arthur J. O'Dwyer said:
Hey, good idea! :)

#include <stdio.h>

#define PADSIZE(n) (sizeof(struct {int flag; char keys[9][3]; \
char pad[n];}))
#define PADOK(n) (PADSIZE(n)%8==0)
#define PAD (PADOK(1)? 1: PADOK(2)? 2: PADOK(3)? 3: PADOK(4)? 4: \
PADOK(5)? 5: PADOK(6)? 6: PADOK(7)? 7: PADOK(8)? 8: -1)

typedef struct {
int flag;
char keys[9][3];
char padding[PAD];
} foo;

(Naturally, the OP should not use this method. Nor should anyone else.)

LCC-Win32 fails on code like this where a structure type is defined in a
situation other than a declaration.

Error padsize.c: 12 missing semicolon after structure declaration
[Repeated 8 times]

This spurious diagnostic actually triggers an "error" condition which
prevents creation of an executable.

On the other hand, MS VC++'s free command-line compiler also doesn't like
your macro much, but at least only warns rather than errors out:

padsize.c(12) : warning C4116: unnamed type definition in parentheses

GCC, BC++ and Turbo C have no problems with your macro.
 

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

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top