struct with one member: padding?

M

Mark

Hello

on many (all?) unix implementations IP address structure is designed this
way:

struct in_addr
{
unsigned long s_addr;
};

Does the Standard allow a C comiler to add padding in such structure? If it
so, then we have to always 'memset' in_addr to 0 before use.

Thanks.

Mark
 
J

John Gordon

In said:
struct in_addr
{
unsigned long s_addr;
};
Does the Standard allow a C comiler to add padding in such structure? If it
so, then we have to always 'memset' in_addr to 0 before use.

If you're accessing in_addr.s_addr, why do you care if there is padding
before or after?

If you're trying to access in_addr as though it were not a struct I can
see why you would care, but that seems to be a pretty egregious error.
 
B

Ben Pfaff

Mark said:
on many (all?) unix implementations IP address structure is designed this
way:

struct in_addr
{
unsigned long s_addr;
};

Does the Standard allow a C comiler to add padding in such
structure?

Yes. (I don't know of any implementations that will.)
 
B

Ben Bacarisse

John Gordon said:
If you're accessing in_addr.s_addr, why do you care if there is padding
before or after?

If you're trying to access in_addr as though it were not a struct I can
see why you would care, but that seems to be a pretty egregious error.

I think that depends how you do it.

It's probably worth pointing out that there can't be any padding before
s_addr, only after. I.e. sizeof (struct in_addr) may be greater than
sizeof (long) but

struct in_addr a;
assert((void *)&a == (void *)&a.s_addr);

can't fail. Thus

unsigned char bytes[sizeof (long)];
memcpy(bytes, &a, sizeof bytes);

kind of fits your "access in_addr as though it were not a struct" but it's
safe.

None the less, I agree that the question hints that something dangerous
might be being considered!
 
A

Andrew Cooper

Given
struct in_addr variable;
then
&variable == &(variable.s_addr)
however
sizeof(variable) =?= sizeof(variable.s_addr)

You can't make any safe portable assumptions about the sizeof the struct and
any/all of its fields.

In practice any CPU you're likely to use will not pad an unsigned long. If you
want to restrict your software to such machines, you're not going to lose too
many customers.

For my code I run a small program as part of the build which does like
int main(int argc, cahr**argv) {
FILE *f = fopen("sizes.h", "w");
fprintf(f,"#define size_unsigned_long %d\n", sizeof(unsigned long));
fprintf(f,"#define size_time_t %d\n", sizeof(time_t));
fprintf(f,"#define size_struct_in_addr %d\n", sizeof(struct in_addr));
...
return 0
}

Then you can do things like
#include "sizes.h"
#if size_unsigned_long!=size_struct_in_addr
#error Cannot compile: sizeof(unsigned long)!=sizeof(struct in_addr)
#endif

There is a different way of doing this which does not rely on a
generated file (so no chance of going stale or missing), nor pollute the
defines with lower case characters.

#define BUILD_BUG_IF(condition) ((void)sizeof(struct {
int:-!!(condition); }))

at which point, your code becomes

BUILD_BUG_IF(sizeof(unsigned long) != sizeof(struct in_addr));

True, your error message then becomes "error: negative width in
bit-field ‘<anonymous>’" or similar, but you do get the file and line
number of the failure, which then allows anyone to see why compiling failed.

~Andrew
 

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,951
Messages
2,570,113
Members
46,699
Latest member
Abigail89S

Latest Threads

Top