offset

H

henry

List,

Does offset mean size different between two structure members?
I expect following output should be i=0,c=1,d=5 and a=6.

But my x86 computer has output,

offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */

printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));

exit(EXIT_SUCCESS);
}

---henry
 
J

James Kuyper

henry said:
List,

Does offset mean size different between two structure members?

I'm not sure exactly what that question means. offsetof() gives a
distance, not a size. Specifically, it's the number of bytes between the
start of the specified structure and the start of the specified member
of that structure.
I expect following output should be i=0,c=1,d=5 and a=6.

You should explain how you reached those conclusions. They are not
impossible, but are extremely unlikely.
But my x86 computer has output,

offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */

printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));

exit(EXIT_SUCCESS);
}

The only portable expectations you should have are as follows:

offsetof(s,i) == 0
offsetof(s,c) >= offsetof(s,i) + sizeof(int)
offsetof(s,d) >= offsetof(s,c) + 1
offsetof(s,a) >= offsetof(s,d) + sizeof(double)

In practice, the first and third >= will probably be ==, but that's not
required by the standard.
 
S

Stephen Sprunk

henry said:
List,

Does offset mean size different between two structure members?
I expect following output should be i=0,c=1,d=5 and a=6.

That would be a truly bizarre system, though theoretically possible.
I'm interested in why you expect those particular values.
But my x86 computer has output,

offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */

printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));

exit(EXIT_SUCCESS);
}

This program is actually pretty good; it does exactly what I think
you're expecting it to. So, the question becomes, why does it give the
values it does?

When the compiler lays out a struct in memory, it is required to lay out
the elements in order, with zero or more bytes of padding after each
element. Since you mention x86, I'll assume the following values:

sizeof(int)==4
sizeof(double)==8

sizeof(char) is always 1, and "a" is a flexible array member which has
an effective size of 0, but we'll ignore that for now and pretend its
size is also 1. So, we have a structure that looks like this in memory:

iiii.c.dddddddd.a.

where the dots represent possible padding. Why is there padding, and
how does the compiler decide how much, if any, to insert? Well, many
CPUs require that data be aligned properly, or at least run slower if it
isn't, so padding keeps the data aligned. For 32-bit system like x86,
this is most easily visualized (IMHO) by looking at memory in 4- or
8-byte rows; without padding, your struct would be laid out like this:

iiii
cddd or iiiicddd
dddd ddddddda
ddda

The CPU won't like d's misalignment, so padding is inserted, perhaps
like this:

iiii
c... iiiic...
dddd or dddddddd
dddd a.......
a...

These offsets (0, 4, 8, 16) match the ones that your program produces.

Now, if you count those bytes, you'll see the total size has expanded to
20 or 24 bytes -- but remember a flexible array member's size is
effectively zero, not one as we pretended above, so the struct actually
looks like this:

iiii
c... or iiiic...
dddd dddddddd
dddd

This size (16) matches the total size that your program produces.

S
 
J

James Kuyper

Gordon said:
No. The offset is the address difference between the member and
the beginning of the structure in bytes.


Why on earth would you expect that? Particularly strange is the
c=1 where the first element of the structure is an int. Yes, it's
POSSIBLE, but rather wierd. You seem to be expecting sizeof(int)
== 1 and sizeof(char) == 4, which is not permitted by the standard.

His numbers could be produced by a perfectly conforming implementation
where sizeof(int) == 1, sizeof(double) == 1, and for some bizarre reason
the compiler decided to insert three bytes of padding between c and d. I
doubt that this is his reason for expecting those numbers, however.
But my x86 computer has output,

offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */

printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));

exit(EXIT_SUCCESS);
}
 
C

CBFalconer

henry said:
Does offset mean size different between two structure members?
I expect following output should be i=0,c=1,d=5 and a=6.
But my x86 computer has output,

offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */
printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));
exit(EXIT_SUCCESS);
}

Note that you have specified an empty array of char for a. This
doesn't trigger an error here, even though I am using -ansi
-pedantic -W -Wall on gcc 3.2.1 to use C90. Note the difference if
you make that part of the struct definition read "char a;" or "char
a[1];"

offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=20
 
J

James Kuyper

CBFalconer said:
henry wrote: ....
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */
printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));
exit(EXIT_SUCCESS);
}

Note that you have specified an empty array of char for a. This
doesn't trigger an error here, even though I am using -ansi
-pedantic -W -Wall on gcc 3.2.1 to use C90.

I've got gcc 4.1.2; it does produce the required diagnostic message when
invoked with those options:

warning: ISO C90 does not support flexible array members

Note to OP: while flexible array members are constraint violations in
C90, they are perfectly acceptable in C99.
 

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,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top