piet@cs.ruu.nl (Piet van Oostrum) (07/13/90)
I am still trying to get the whole scoop on bit-field alignment in the HP-UX cc compiler on HP9000/300. I detected another case where the bit-field was aligned, which is actually more in line with what others do - if there were not a case that I don't understand - struct test { /* char p;*/ int a:14; int b:20; short c:5; } x; This case (with the char p commented out) aligns b on a 2-byte boundary, presumably because it would otherwise cross a 4-byte boundary, although 4-byte boundaries are not special in records. But if the char p is inserted, no padding is done, the field a doesn't even start on a 2-byte boundary. Now I don't understand what the underlying algorithm is. This might even be a bug. -- Piet* van Oostrum, Dept of Computer Science, Utrecht University, Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-531806 Uucp: uunet!mcsun!ruuinf!piet Telefax: +31-30-513791 Internet: piet@cs.ruu.nl (*`Pete')
mike@hpfcso.HP.COM (Mike McNelly) (07/17/90)
> / hpfcso:comp.sys.hp / piet@cs.ruu.nl (Piet van Oostrum) / 2:16 am Jul 13, 1990 / > I am still trying to get the whole scoop on bit-field alignment in the > HP-UX cc compiler on HP9000/300. I detected another case where the > bit-field was aligned, which is actually more in line with what others do - > if there were not a case that I don't understand - > > struct test { > /* char p;*/ > int a:14; > int b:20; > short c:5; } x; > > This case (with the char p commented out) aligns b on a 2-byte boundary, > presumably because it would otherwise cross a 4-byte boundary, although > 4-byte boundaries are not special in records. But if the char p is > inserted, no padding is done, the field a doesn't even start on a 2-byte > boundary. Now I don't understand what the underlying algorithm is. This > might even be a bug. > -- > Piet* van Oostrum, Dept of Computer Science, Utrecht University, > Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. > Telephone: +31-30-531806 Uucp: uunet!mcsun!ruuinf!piet > Telefax: +31-30-513791 Internet: piet@cs.ruu.nl (*`Pete') > ---------- The best and most current source of information about bitfields on Series 300 is the HP-UX Portability Guide, HP Part Number 98794-90046. The information below was an original source for that discussion although I believe that signed bitfields are now supported. Mike McNelly mike%hpfcla@hplabs.hp.com ======================================================================= Bitfields are assigned left to right and are unsigned regardless of the declared type. They are aligned so that they do not violate the alignment restriction of the declared type. Consequently some padding within the structure may be required. For example, struct foo { unsigned int a:3, b:3, c:3, d:3; unsigned int remainder:20; }; For the above struct, sizeof(struct foo) would return 4 (bytes) because none of bitfields straddle a 4 byte boundary. On the other hand, the following struct declaration will have a larger size. struct foo2 { unsigned char a:3, b:3, c:3, d:3; unsigned int remainder:20; }; In this struct declaration the assignment of data space for c must be aligned so as not to violate a byte boundary, which is the normal alignment of unsigned char. Consequently two undeclared bits of padding are added by the compiler so that c is aligned on a byte boundary. sizeof(struct foo2) therefore returns 6 (bytes). Bitfields on Series 200, 300, and 500 machines cannot exceed the size of the declared type in length. Therefore the largest possible bitfield is 32 bits. All scalar types are permissable to declare bitfields, including enums. However, they are inherently unsigned.
piet@cs.ruu.nl (Piet van Oostrum) (07/18/90)
In article <7370172@hpfcso.HP.COM>, mike@hpfcso (Mike McNelly) writes: | |The best and most current source of information about bitfields on |Series 300 is the HP-UX Portability Guide, HP Part Number 98794-90046. |The information below was an original source for that discussion |although I believe that signed bitfields are now supported. | |Mike McNelly |mike%hpfcla@hplabs.hp.com |======================================================================= | |Bitfields are assigned left to right and are unsigned regardless of the |declared type. They are aligned so that they do not violate the |alignment restriction of the declared type. Consequently some padding |within the structure may be required. | |For example, | | struct foo | { | unsigned int a:3, b:3, c:3, d:3; | unsigned int remainder:20; | }; | |For the above struct, sizeof(struct foo) would return 4 (bytes) because |none of bitfields straddle a 4 byte boundary. On the other hand, the |following struct declaration will have a larger size. | | struct foo2 | { | unsigned char a:3, b:3, c:3, d:3; | unsigned int remainder:20; | }; | |In this struct declaration the assignment of data space for c must be |aligned so as not to violate a byte boundary, which is the normal |alignment of unsigned char. Consequently two undeclared bits of padding |are added by the compiler so that c is aligned on a byte boundary. |sizeof(struct foo2) therefore returns 6 (bytes). | |Bitfields on Series 200, 300, and 500 machines cannot exceed the size of |the declared type in length. Therefore the largest possible bitfield is |32 bits. All scalar types are permissable to declare bitfields, |including enums. However, they are inherently unsigned. I had read this passage several times, and I have tried to attach some kind of semantics to it. I think the wording is highly ambiguous, but I thik I have grasped its meaning now. Let me try to formulate the underlying algorithm. 1. A halfword is a sequence of two bytes starting at an even address, a longword is a sequence of four bytes starting at any EVEN address. (these are the words as I am going to use them below. 2. A bitfield that is declared as a char must fit into a byte, a field that is declared as a short must fit into a halfword (as defined above), and a field that is declared as an int or long must fit into a longword. If the field does not fit, it is aligned on the next boundary (1 byte for char, 2 bytes for short/int/long). The following examples illustrate this: I. struct test { int a:14; int b:20; int c:5; } x; b will be aligned because otherwise it would occupy (part of) bytes 1,2,3,4, which is one byte more than the longword starting at byte 0. II. struct test { char p; int a:14; int b:20; int c:5; } x; Now NO PADDING is required because a fits in the logword starting at byte 0 and b spans byte 2,3,4,5 which fits into the longword starting at byte 2. III. struct test { char p; short a:14; int b:20; int c:5; } x; In this case a is defined as short so it has to fit into a halfword. It doesn't fit into the halfword at byte 0, so it is aligned on byte 2. -- Piet* van Oostrum, Dept of Computer Science, Utrecht University, Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-531806 Uucp: uunet!mcsun!ruuinf!piet Telefax: +31-30-513791 Internet: piet@cs.ruu.nl (*`Pete')
mike@hpfcso.HP.COM (Mike McNelly) (07/19/90)
Your interpretation is correct. Mike McNelly mike%hpfcla@hplabs.hp.com