By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,198 Members | 954 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,198 IT Pros & Developers. It's quick & easy.

sizeof struct returning unexpected results

P: n/a
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};

Checking the sizeof variables declared to be of this type, I get 64
bits, when really the size of a short is 16 bits, and the size of an
int is 32 bits. Declaring the struct to have two shorts produces
expected results, and declaring it to have one short also produces
expected results.

I do understand what is going on here. The size is being adjusted
or "aligned" (I don't want to misuse that term so correct me if I used
it wrong) to the size of the largest constituent element. However, I
would like to prevent this as it does have the end result of munging
communication as it relates to this protocol.

I originally discovered this in D, where I had a struct which
contained shorts, ints, and a long. I was able to reproduce it in C,
so I figure it's a more basic issue with a generic response
(hopefully).

What can I do to have a struct, declared as above, either return a
size of 6, or be manipulated so as to present itself as a string of 48
bits?

Thanks everyone, for your time.
Nov 14 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
On 20 Aug 2004 09:40:53 -0700, se******@bluebeard.org (Sean) wrote:
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};

Checking the sizeof variables declared to be of this type, I get 64
bits, when really the size of a short is 16 bits, and the size of an
int is 32 bits. Declaring the struct to have two shorts produces
expected results, and declaring it to have one short also produces
expected results.

I do understand what is going on here. The size is being adjusted
or "aligned" (I don't want to misuse that term so correct me if I used
it wrong) to the size of the largest constituent element. However, I
would like to prevent this as it does have the end result of munging
communication as it relates to this protocol.

I originally discovered this in D, where I had a struct which
contained shorts, ints, and a long. I was able to reproduce it in C,
so I figure it's a more basic issue with a generic response
(hopefully).

What can I do to have a struct, declared as above, either return a
size of 6, or be manipulated so as to present itself as a string of 48
bits?

Thanks everyone, for your time.


Depending upon your compiler you should investigate a method to allow
the structure to be packed.

With Gcc you may use __attribute__ ((packed)) for example.

Eg.

struct Tester {
unsigned short first;
unsigned int second;
} __attribute__ ((packed));

l8r
Nov 14 '05 #2

P: n/a
Sean wrote:
Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};

Checking the sizeof variables declared to be of this type, I get 64
bits, when really the size of a short is 16 bits, and the size of an
int is 32 bits. Declaring the struct to have two shorts produces
expected results, and declaring it to have one short also produces
expected results.


Your compiler is padding the structure so that's its a multiple of 8 bytes.
The compiler is free to do this and usually it's to make optimizations
possible [and loads/stores quicker].

If you want exact sizes you'll have to use compiler specific ``attributes''
which are off topic here.

Tom
Nov 14 '05 #3

P: n/a
Sean wrote:
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.


This is Question 2.12 in the comp.lang.c Frequently
Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

.... and you're not going to like the answer.

--
Er*********@sun.com

Nov 14 '05 #4

P: n/a
Sean <se******@bluebeard.org> wrote:
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results. Here is a test struct I wrote: struct Tester {
unsigned short first;
unsigned int second;
}; Checking the sizeof variables declared to be of this type, I get 64
bits, when really the size of a short is 16 bits, and the size of an
int is 32 bits. Declaring the struct to have two shorts produces
expected results, and declaring it to have one short also produces
expected results. I do understand what is going on here. The size is being adjusted
or "aligned" (I don't want to misuse that term so correct me if I used
it wrong) to the size of the largest constituent element. However, I
No, its get aligned to whatever the compiler thinks is reasonable.
Part of the problem is that on some systems it's e.g. not allowed
to access integers that don't start on a address that can be divided
by 4. And when a short int has a size of 2 and there would be no
padding the int would start on an address that only can be divided
by 2 but not by 4 and an read or write access to that int would crash
the program.
would like to prevent this as it does have the end result of munging
communication as it relates to this protocol. What can I do to have a struct, declared as above, either return a
size of 6, or be manipulated so as to present itself as a string of 48
bits?


Some compilers let you invoke some compiler-specific magic that
makes it leave out the padding for the structure - see your
compiler documentation for that. But there's no portable way to
do it.

If you want to stay portable use an array of unsigned chars, long
enough to hold the data, instead of a structure. Copy them into (or
out of) the array using memcpy() and finally write that array to
the file or read it back, i.e. something like this:

unsigned char buf[ sizeof( unsigned short ) + sizeof ( unsigned int ) ];
unsigned short first;
unsigned int second;
FILE *fp;

....

memcpy( buf, &first, sizeof first );
memcpy( buf + sizeof first, &second, sizeof second );
if ( fwrite( buf, sizeof buf, 1, fp ) != sizeof buf )
exit( EXIT_FAILURE );

....

if ( fread( buf, sizeof buf, 1, fp ) != sizeof buf )
exit( EXIT_FAILURE );
memcpy( &first, buf, sizeof first );
memcpy( &second, buf + sizeof first, sizeof second );

If this looks too ugly hide it away in a function;-)

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #5

P: n/a
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Sean wrote:
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};

Checking the sizeof variables declared to be of this type, I get 64
bits,
How do you determine this? sizeof measures in char units, not bit units.

when really the size of a short is 16 bits,
You know this because...?
and the size of an
int is 32 bits.
You know this because...?
Declaring the struct to have two shorts produces
expected results, and declaring it to have one short also produces
expected results.

I do understand what is going on here. The size is being adjusted
or "aligned" (I don't want to misuse that term so correct me if I used
it wrong) to the size of the largest constituent element.
No, not really.

The elements of your struct are individually aligned on boundaries that
your compiler has determined they must be aligned on. A hypothetical
example would be that
sizeof (short) is 2,
short elements must be aligned on a 2 char boundary,
sizeof (int) is 4, and
int elements must be aligned on a 4 char boundary,
meaning that

struct {
short n1;
int n2;
};

resulting in placement of n1 taking up 2 chars, and n2 not being
able to start at the next available char because it needs to be on
a 4 char boundary. The compiler would 'inject' some padding between
the short and the int so as to make the int fall on a 4 char boundary.

However,

struct {
int n2;
short n1;
};

would result in the placement of n2 taking up 4 chars, and n1 being
able to start on a 2 char boundary. In this case the compiler would
not have to inject padding.
However, I
would like to prevent this as it does have the end result of munging
communication as it relates to this protocol.


This is a compiler-dependant issue. You have to go back to your
compiler's documentation and find a way to tell it to use different
alignment rules. In some compilers, this can be a #pragma preprocessor
directive, while others will use a commandline option.

This is not a C issue.

[snip]

- --

Lew Pitcher, IT Consultant, Enterprise Application Architecture
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFBJi4fagVFX4UWr64RAnQsAKCJpqzpHOC4CIW6L9Vq5M S8GmQlkgCeIA48
PsiyPVMAB/jXI2XZABRzS4E=
=38vT
-----END PGP SIGNATURE-----
Nov 14 '05 #6

P: n/a
On Fri, 20 Aug 2004 17:50:57 +0100, Mr Wibble <wi****@eurobell.co.uk>
wrote in comp.lang.c:
On 20 Aug 2004 09:40:53 -0700, se******@bluebeard.org (Sean) wrote:
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};

Checking the sizeof variables declared to be of this type, I get 64
bits, when really the size of a short is 16 bits, and the size of an
int is 32 bits. Declaring the struct to have two shorts produces
expected results, and declaring it to have one short also produces
expected results.

I do understand what is going on here. The size is being adjusted
or "aligned" (I don't want to misuse that term so correct me if I used
it wrong) to the size of the largest constituent element. However, I
would like to prevent this as it does have the end result of munging
communication as it relates to this protocol.

I originally discovered this in D, where I had a struct which
contained shorts, ints, and a long. I was able to reproduce it in C,
so I figure it's a more basic issue with a generic response
(hopefully).

What can I do to have a struct, declared as above, either return a
size of 6, or be manipulated so as to present itself as a string of 48
bits?

Thanks everyone, for your time.


Depending upon your compiler you should investigate a method to allow
the structure to be packed.

With Gcc you may use __attribute__ ((packed)) for example.

Eg.

struct Tester {
unsigned short first;
unsigned int second;
} __attribute__ ((packed));

l8r


This is actually an extremely bad idea. On some platforms it will
only produce code that executes more slowly. On others, violating the
hardware alignment requirements will result in hardware exceptions
killing the program.

And it's off-topic here.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #7

P: n/a
"Sean" <se******@bluebeard.org> wrote in message
news:d5**************************@posting.google.c om...
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};


You could try reversing the order. By putting the int first it will be
aligned to whatever boundary it requires "outside" of the structure. Then
the short _may_ be able to skip the padding, if it is allowed to align right
behind the int. It's worth testing, just to know for future reference on
that compiler / platform.

--
Mabden
Nov 14 '05 #8

P: n/a
"Mabden" <mabden@sbc_global.net> wrote in message
news:F8*****************@newssvr29.news.prodigy.co m...
"Sean" <se******@bluebeard.org> wrote in message
news:d5**************************@posting.google.c om...
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};


You could try reversing the order. By putting the int first it will be
aligned to whatever boundary it requires "outside" of the structure. Then
the short _may_ be able to skip the padding, if it is allowed to align
right behind the int.


On most implementations there will still be padding after the unsigned
short, and sizeof(struct Tester) will be unchanged.

Alex
Nov 14 '05 #9

P: n/a
"Alex Fraser" <me@privacy.net> wrote in message
news:2o************@uni-berlin.de...
"Mabden" <mabden@sbc_global.net> wrote in message
news:F8*****************@newssvr29.news.prodigy.co m...
"Sean" <se******@bluebeard.org> wrote in message
news:d5**************************@posting.google.c om...
I have a struct that I wrote to test a protocol. The idea I had was
to just declare the elements of the struct in the order in which they
are sent and received as defined by the protocol. However, writing
this struct to a file produces unexpected results.

Here is a test struct I wrote:

struct Tester {
unsigned short first;
unsigned int second;
};


You could try reversing the order. By putting the int first it will be
aligned to whatever boundary it requires "outside" of the structure. Then the short _may_ be able to skip the padding, if it is allowed to align
right behind the int.


On most implementations there will still be padding after the unsigned
short, and sizeof(struct Tester) will be unchanged.


Of course. That is why I said to "try it" and it "may work", and in the part
you snipped, that "It's worth testing, just to know for future reference on
that compiler / platform."

But thanks for the useful insights you provided.

--
Mabden

Nov 14 '05 #10

P: n/a
Jack Klein <ja*******@spamcop.net> writes:
On Fri, 20 Aug 2004 17:50:57 +0100, Mr Wibble <wi****@eurobell.co.uk>
wrote in comp.lang.c:

[...]
Depending upon your compiler you should investigate a method to allow
the structure to be packed.

With Gcc you may use __attribute__ ((packed)) for example.

Eg.

struct Tester {
unsigned short first;
unsigned int second;
} __attribute__ ((packed));


This is actually an extremely bad idea. On some platforms it will
only produce code that executes more slowly. On others, violating the
hardware alignment requirements will result in hardware exceptions
killing the program.


Methods that allow packing structures are compiler-specific and
extremely non-portable (see question 2.12 in the C FAQ).

However, if a compiler does provide such a mechanism, it will almost
certainly do whatever is necessary to generate the right code to
access the members without killing the program. In the case of
"struct Tester" above, this might involve using two instructions to
access the halves of the (misaligned) member "second", or using the
equivalent of memcpy().

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.