stanonik@nprdc.navy.mil (Ron Stanonik) (04/11/91)
We ran into a little problem while porting some 4.3bsd/sunos
code to a 3b2 running sysVr3.2. The problem was that on the
3b2, structs are not only aligned on 32 bit boundaries (which
we expected), but also padded to 32 bit boundaries. For example,
here's a little program
struct s0 { char c[2]; };
struct s1 { struct s0 s0; short s; } x1;
main()
{
printf("offset of short = %d\n", (int)&x1.s - (int)&x1);
}
We expected the short x1.s to be two bytes from the start of the struct x1.
That's what happens on vax's running 4.3bsd, sun's running sunos4.1, hp's
running hpux, 386's running sysVr4. But on the 3b2 running sysVr3.2,
x1.s is offset 4 bytes, apparently because the struct s0 is padded
out to a 32 bit boundary in s1. Is this a "feature" of sysVr3.2,
or just the 3b2's? From K&R second edition, I gather there are no
assurances regarding alignment or padding in this instance, but this
behaviour seems contrary to the usefulness of C as a low level language.
(Specfically we ran into this because EGP headers end on a 16 bit
boundary, immediately followed by the remainder of the EGP packet.
Because the header was padded, the remainder of the packet was
incorrectly positioned.)
Thanks,
Ron Stanonik
stanonik@nprdc.navy.mil
ucsd!nprdc!stanonik
chrisb@risky.Convergent.COM (Chris Bertin) (04/19/91)
In article <14082@arctic.nprdc.navy.mil> stanonik@nprdc.navy.mil (Ron Stanonik) writes: ... alignment problem description deleted ... > ... From K&R second edition, I gather there are no >assurances regarding alignment or padding in this instance, but this >behaviour seems contrary to the usefulness of C as a low level language. > If C had per-structure alignment directives, it would make it a lot more useful as a low level language, but it would also make it a lot less portable. Some compilers use environment variables (STALIGN, DBLALIGN in Motorola compilers) to align structures. Perhaps the 3B2 has something of the sort. This could help you in this case, although these variables may cause major other problems if you end up with standard (/usr/include/...) structures aligned differently between your .o files and the libraries. -- Chris Bertin | chrisb@risky.Convergent.COM Unisys | or (408) 435-3762 | ...!uunet!pyramid!ctnews!risky!chrisb
stanonik@nprdc.navy.mil (Ron Stanonik) (04/20/91)
Alignment I can understand, but padding just seems like the compiler writers got lazy. It also meant that sizeof(struct packet) wasn't the packet size, when the packet didn't end on a 32 bit boundary; ie, we had to count up the bytes by hand to figure packet sizes. We looked in vain for any cc flags that might disable padding, but, as you said, we'd be wary of using such a flag for fear of fouling up some sysV.3.2 include that expected the padding. Did the 3b2 folks really use this compiler to compile the kernel; ie, they didn't encounter any problems with this padding? Thanks, Ron Stanonik stanonik@nprdc.navy.mil ucsd!nprdc!stanonik
jim@segue.segue.com (Jim Balter) (04/21/91)
In article <14082@arctic.nprdc.navy.mil> stanonik@nprdc.navy.mil (Ron Stanonik) writes: >The problem was that on the >3b2, structs are not only aligned on 32 bit boundaries (which >we expected), but also padded to 32 bit boundaries. If a struct is aligned on a 32 bit boundary, that implies that it is padded to a 32-bit boundary. Consider struct foo x[2]; x[1] is aligned on a 32-bit boundary. Thus x[0] is padded to a 32-bit boundary. If it weren't, then sizeof(x) != sizeof(x[0]) + sizeof(x[1]). If C had both a padd_sizeof and an unpadded_sizeof, then this wouldn't need to be, but it doesn't. >here's a little program > struct s0 { char c[2]; }; > > struct s1 { struct s0 s0; short s; } x1; > > main() > { > printf("offset of short = %d\n", (int)&x1.s - (int)&x1); > } > >We expected the short x1.s to be two bytes from the start of the struct x1. Some compilers are smart enough to align structures based on what they need. Apparently, your 3b2 compiler is aligning all structures on 32-bit boundaries even when they only need to be aligned on char boundaries. A structure needs to be as aligned as its most aligned member, but no more. And there mustn't be padding before the first member. Thus, an s0 embedded in an s1 needs to be short-aligned, but no more. >But on the 3b2 running sysVr3.2, >x1.s is offset 4 bytes, apparently because the struct s0 is padded >out to a 32 bit boundary in s1. Is this a "feature" of sysVr3.2, >or just the 3b2's? It's just a "feature" of the particular compiler you are using. >From K&R second edition, I gather there are no >assurances regarding alignment or padding in this instance, but this >behaviour seems contrary to the usefulness of C as a low level language. ANSI requires that an implementation document the alignment used, but it can't mandate what that alignment is, precisely to make C useful as a low level language, because different hardware has different requirements. The expectation is that the alignment used suits the hardware, and that structures are not more aligned than necessary. You just happen to be using a low-quality compiler. If the structures you are dealing with are not being transmitted between machines, there shouldn't be a problem unless there is some invalid use of casts or unions. If they are being transmitted between machines, they should be converted to and from a canonical form. Is is a mistake to make assumptions about byte order or alignment consistency among different machine archtectures.