www.digitalmars.com         C & C++   DMDScript  

D - [BUG] Struct alignment (Was Re: Struct sizes - converting C to D)

reply Adam Harper <a-news-d harper.nu> writes:
The code:

 import std.c.stdio;
 
 align(2)
 {
   struct Test{short s; char c;};
 };
 
 int main(char[][] args)
 {
   printf("%d\n", Test.size);
   
   return 0;
 };

Outputs:
 3

It should output 4 (if the struct is aligned to the nearest two bytes then the struct should be four bytes in size, not three). This was tested on Linux using DMD 0.82 (with GCC 3.3.3 as the linker). The corresponding C code:
 #include <stdio.h>
 
 #pragma pack(2)
 struct Test{short s; char c;};
 #pragma pack()
 
 int main(int argc, char** argv)
 {
   printf("%d\n", sizeof(struct Test));
   
   return 0;
 };

Outputs:
 4

As expected (compiled with GCC 3.3.3 on Linux). -- Adam (Note: I had originally posted a similar message under the title "Struct sizes - converting C to D", but wasn't particularly clear and had managed to miss the simplicity of the problem. So, whilst Walter may have picked up on the underlying problem from those posts I thought it best to just post a clear, succinct, bug report.)
Apr 23 2004
next sibling parent reply Juan C <Juan_member pathlink.com> writes:
<snipple>
 align(2)
 {
   struct Test{short s; char c;};
 };
   printf("%d\n", Test.size);

 3


Looks OK to me, the struct _is_ three bytes in size. Maybe there's a flaw in C that D fixes. What if the char comes before the short?
Apr 23 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Juan C" <Juan_member pathlink.com> wrote in message
news:c6bqgl$1m36$1 digitaldaemon.com...
 <snipple>
 align(2)
 {
   struct Test{short s; char c;};
 };
   printf("%d\n", Test.size);

 3


Looks OK to me, the struct _is_ three bytes in size. Maybe there's a flaw in C that D fixes.

It is not. It is 4 bytes. It could only be 3 if the alignment was 1. The way it works is to denote the boundary on which each of an array of such structures would align. If the size of this was truly 3 - when correct, of course, I believe that the compiler has it wrong in actuality - then the packing of array elements would not differ between align(1) and align(2), which is clearly nonsensical. The only align(?) agnosticism in this case should be between 2 and 4, since the actual total size is 3. Is that clear as custard? ;)
 What if the char comes before the short?

There should theoretically be no difference, since alignment is (2).
Apr 24 2004
parent reply Juan C <Juan_member pathlink.com> writes:
<snip>
The way it works is to denote the boundary on which each of an array of such
structures would align. If the size of this was truly 3 - when correct, of

That's not how I read it. I read it as alignment of fields _within_ the structure and not affecting anything _outside_ the structure. If you declare an array of them and want what you describe you would also have to use align(2) _on the array_. I do, however, understand that what you describe is what was intended to be implemented. But the way it is (even if it's a misimplementation) is more flexible, and desirable on its own.
Apr 24 2004
next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Juan C schrieb:

 <snip>
 
The way it works is to denote the boundary on which each of an array of such
structures would align. If the size of this was truly 3 - when correct, of

</snip> That's not how I read it. I read it as alignment of fields _within_ the structure and not affecting anything _outside_ the structure. If you declare an array of them and want what you describe you would also have to use align(2) _on the array_.

The problem is, you can iterate through an array by using element-type.sizeof - which may not work then. -eye
Apr 24 2004
parent reply Juan C <Juan_member pathlink.com> writes:
<snip>
The problem is, you can iterate through an array by using 
element-type.sizeof - which may not work then.

That must be why you can't specify an alignment for array elements, my mistake. Anyway, as align is currently implemented, what you describe is still not broken.
Apr 24 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Juan C schrieb:
 That must be why you can't specify an alignment for array elements, my mistake.
 
 Anyway, as align is currently implemented, what you describe is still not
 broken.

True, but the performance will be so sluggish that it kills all of the sense for alignment in the first place. There should be a way to specify that not only structure members, but also the complete structure size has to be aligned. When performance is conserned, the same size for element and for whole structure alignement makes sense. Otherwise there may also be some memory considerations etc. For any sort of file exchange, "packed" (byte aligment) is always appropriate. -eye
Apr 24 2004
prev sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Juan C" <Juan_member pathlink.com> wrote in message
news:c6e499$19u9$1 digitaldaemon.com...
 <snip>
The way it works is to denote the boundary on which each of an array of such
structures would align. If the size of this was truly 3 - when correct, of

That's not how I read it. I read it as alignment of fields _within_ the structure and not affecting anything _outside_ the structure. If you declare an array of them and want what you describe you would also have to use align(2) _on the array_. I do, however, understand that what you describe is what was intended to be implemented. But the way it is (even if it's a misimplementation) is more flexible, and desirable on its own.

How can it be desirable when it is meaningless? align(2) cannot, by definition, yield a structure with a (size % 2) != 0. That is the very definition of packing alignment!
Apr 24 2004
parent reply Juan C <Juan_member pathlink.com> writes:
<snip>
How can it be desirable when it is meaningless? align(2) cannot, by definition,
yield a structure with a (size % 2) != 0. That is the very definition of packing
alignment!

You're obviously using the definition of such which was _supposed to be_ implemented, not that which _was_ implemented. I still say both should be available, perhaps fix align, but add an attribute to mean this kind.
Apr 24 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Juan C wrote:

 <snip>
 
How can it be desirable when it is meaningless? align(2) cannot, by definition,
yield a structure with a (size % 2) != 0. That is the very definition of packing
alignment!

</snip> You're obviously using the definition of such which was _supposed to be_ implemented, not that which _was_ implemented. I still say both should be available, perhaps fix align, but add an attribute to mean this kind.

If you want "this kind", there's always this: struct Test { align(2) short s; align(1) char c; } Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Apr 26 2004
prev sibling parent reply Adam Harper <a-news-d harper.nu> writes:
On Fri, 23 Apr 2004 19:24:05 +0000 (UTC)
Juan C <Juan_member pathlink.com> wrote:

 Looks OK to me, the struct _is_ three bytes in size. Maybe there's a
 flaw in C that D fixes.

Not according to the D spec. From http://www.digitalmars.com/d/attribute.html#align:
 Integer specifies the alignment which matches the behavior of the
 companion C compiler when non-default alignments are used

Apr 23 2004
parent Juan C <Juan_member pathlink.com> writes:
<snip>
 Integer specifies the alignment which matches the behavior of the
 companion C compiler when non-default alignments are used


Well, you're right that it does not behave the same as DMC (and Borland as well), but I prefer this behaviour. May need another attribute so the user can choose which is desired. As far as my opinion goes, the alignment only applies to where the member _starts_, not where it ends. And it also doesn't apply to where the _next_ structure starts either.
Apr 23 2004