digitalmars.D - Incorrect struct and union size. Possible bug?
- MicroWizard (40/40) Nov 20 2004 I wrote a program to access Win32 character based console form D, but go...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (8/66) Nov 20 2004 In D, declaring a union does *not* mean allocating a variable...
- Russ Lewis (7/35) Nov 22 2004 Actually, you aren't quite correct here. The syntax that MicroWizard
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (12/72) Nov 22 2004 True, but that wasn't the syntax used in the previous example... :-P
- Russ Lewis (2/14) Nov 22 2004
- Sean Kelly (15/25) Nov 22 2004 It should print 1 byte (or 4 bytes, I'm not sure how big empty classes a...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (10/26) Nov 22 2004 (structs are 1 byte when compiled with gdc,
- Walter (3/13) Dec 04 2004 It should print 1. The reason is to be compatible with C.
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (8/19) Dec 05 2004 And I understood the rationale there was just so that it
- Sean Kelly (8/26) Dec 05 2004 Yup. C++ requires that all objects have a unique address, and thus they...
I wrote a program to access Win32 character based console form D, but got strange screen addressing problems. When I dig into the deep, I have found this. In the following program when I mix structs and unions, the compiler does not calculate with the last struct element(s). alias char CHAR; alias wchar WCHAR; alias ushort WORD; struct TST { union Char{ WCHAR UnicodeChar; CHAR AsciiChar; }; WORD Attributes; }; struct TST2 { WCHAR UnicodeChar; WORD Attributes; }; struct TST3 { union Char{ WCHAR UnicodeChar; CHAR AsciiChar; }; union Char2{ WCHAR UnicodeChar; CHAR AsciiChar; }; }; void main(char[][] arg) { printf("TST.sizeof=%d,TST2.sizeof=%d,TST3.sizeof=%d\n", TST.sizeof, TST2.sizeof, TST3.sizeof); } The result is: TST.sizeof=2,TST2.sizeof=4,TST3.sizeof=1 And what I expect: TST.sizeof=4,TST2.sizeof=4,TST3.sizeof=4 Or missed I something completely? Best regards, Tamas Nagy
Nov 20 2004
MicroWizard wrote:struct TST { union Char{ WCHAR UnicodeChar; CHAR AsciiChar; }; WORD Attributes; }; struct TST2 { WCHAR UnicodeChar; WORD Attributes; }; struct TST3 { union Char{ WCHAR UnicodeChar; CHAR AsciiChar; }; union Char2{ WCHAR UnicodeChar; CHAR AsciiChar; }; }; void main(char[][] arg) { printf("TST.sizeof=%d,TST2.sizeof=%d,TST3.sizeof=%d\n", TST.sizeof, TST2.sizeof, TST3.sizeof); } The result is: TST.sizeof=2,TST2.sizeof=4,TST3.sizeof=1 And what I expect: TST.sizeof=4,TST2.sizeof=4,TST3.sizeof=4 Or missed I something completely?In D, declaring a union does *not* mean allocating a variable... (even an empty structure: { } has a .sizeof of 1, a little quirk) This works:union CharU{ WCHAR UnicodeChar; CHAR AsciiChar; } union Char2U{ WCHAR UnicodeChar; CHAR AsciiChar; } struct TST { CharU Char; WORD Attributes; } struct TST2 { WCHAR UnicodeChar; WORD Attributes; } struct TST3 { CharU Char; Char2U Char2; }(note: there is no semicolon after union or struct definitions) Outputs: TST.sizeof=4,TST2.sizeof=4,TST3.sizeof=4 --anders
Nov 20 2004
Anders F Björklund wrote:In D, declaring a union does *not* mean allocating a variable... (even an empty structure: { } has a .sizeof of 1, a little quirk)Actually, you aren't quite correct here. The syntax that MicroWizard used was correct, and is known as an "anonymous union." The documentation mentions that they are supported, provided that they are part of a struct. See http://digitalmars.com/d/struct.html I tested this program on Linux (0.106), and it works as expected:struct foo { align(1): union { char c; short s; } int i; } import std.stdio; void main() { foo f[2]; foo *ptr = cast(foo*)0; writef("%x %x\n" "%d %d %d\n" "%d %d %d\n" "%d %d %d\n", cast(int)&f[0], cast(int)&f[1], f.sizeof,f[0].sizeof,foo.sizeof, foo.c.sizeof, foo.s.sizeof, foo.i.sizeof, cast(int)&ptr.c, cast(int)&ptr.s, cast(int)&ptr.i); }It outputs the following:ffffffffbfee0710 ffffffffbfee0716 12 6 6 1 2 4 0 0 2
Nov 22 2004
Russ Lewis wrote:True, but that wasn't the syntax used in the previous example... :-P They were all named ?In D, declaring a union does *not* mean allocating a variable...Actually, you aren't quite correct here. The syntax that MicroWizard used was correct, and is known as an "anonymous union." The documentation mentions that they are supported, provided that they are part of a struct. See http://digitalmars.com/d/struct.htmlstruct TST { union Char{ WCHAR UnicodeChar; CHAR AsciiChar; } WORD Attributes; } struct TST2 { WCHAR UnicodeChar; WORD Attributes; } struct TST3 { union Char{ WCHAR UnicodeChar; CHAR AsciiChar; } union Char2{ WCHAR UnicodeChar; CHAR AsciiChar; } }TST.sizeof=2,TST2.sizeof=4,TST3.sizeof=1 (small sizes due to no Char fields present) They could be anonymized:struct TST { union { WCHAR UnicodeChar; CHAR AsciiChar; } WORD Attributes; } struct TST2 { WCHAR UnicodeChar; WORD Attributes; } struct TST3 { union { WCHAR UnicodeChar; CHAR AsciiChar; } union { WCHAR UnicodeChar2; CHAR AsciiChar2; } }TST.sizeof=4,TST2.sizeof=4,TST3.sizeof=4 (and losing one layer of indirection too) Thanks for pointing that out, the D spec is kinda terse sometimes... --anders PS. This is still a little quirky:struct NULL { } import std.stdio; void main() { writefln("%d", NULL.sizeof); }(Hint: it does not print zero bytes)
Nov 22 2004
Eek! You're right, sorry... Anders F Björklund wrote:Russ Lewis wrote:True, but that wasn't the syntax used in the previous example... :-PIn D, declaring a union does *not* mean allocating a variable...Actually, you aren't quite correct here. The syntax that MicroWizard used was correct, and is known as an "anonymous union." The documentation mentions that they are supported, provided that they are part of a struct. See http://digitalmars.com/d/struct.html
Nov 22 2004
In article <cnt11q$2qra$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...PS. This is still a little quirky:It should print 1 byte (or 4 bytes, I'm not sure how big empty classes are in D). The reason is that for a class to be uniquely addressable it has to occupy space in memory. C++ is the same way. C++ does have something called the "base class optimization" however, that allows empty base classes to have zero size in derived classes. ie. class Base {} class Derived : Base {} printf( "base size: %u\nderived size: %u\n", Base.sizeof, Derived.sizeof ); This should print: base size: 4 derived size: 4 (it looks like the size of an empty class is int.sizeof after all) Seanstruct NULL { } import std.stdio; void main() { writefln("%d", NULL.sizeof); }(Hint: it does not print zero bytes)
Nov 22 2004
Sean Kelly wrote:It should print 1 byte (or 4 bytes, I'm not sure how big empty classes are in D). The reason is that for a class to be uniquely addressable it has to occupy space in memory. C++ is the same way. C++ does have something called the "base class optimization" however, that allows empty base classes to have zero size in derived classes. ie.(structs are 1 byte when compiled with gdc, and both the base and derived class are 4) Interesting! The following little C snippet:#include <stdio.h> struct empty { }; int main(void) { printf("%d\n",sizeof(struct empty)); return 0; }Prints "0" compiled with gcc, and "1" with g++. (since structs are classes in C++, no doubt...) Just a little weird, it's not that it's used. :-) --anders PS. But gcc -Wall -pedantic croaks: "warning: struct has no members"
Nov 22 2004
"Anders F Björklund" <afb algonet.se> wrote in message news:cnt11q$2qra$1 digitaldaemon.com...PS. This is still a little quirky:It should print 1. The reason is to be compatible with C.struct NULL { } import std.stdio; void main() { writefln("%d", NULL.sizeof); }(Hint: it does not print zero bytes)
Dec 04 2004
Walter wrote:And I understood the rationale there was just so that it would allocate *something*, to be able to adress later on ? null structures and classes are probably quite rare in reality, I just found it interesting that I got different {} results: gdc:It should print 1. The reason is to be compatible with C.struct NULL { }(Hint: it does not print zero bytes)struct: 4 class: 1g++:struct: 1 class: 4--anders
Dec 05 2004
In article <coukni$1kke$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...Walter wrote:Yup. C++ requires that all objects have a unique address, and thus they all occupy at least one byte. The empty base class optimization tend to help keep derived class size down however.And I understood the rationale there was just so that it would allocate *something*, to be able to adress later on ?It should print 1. The reason is to be compatible with C.struct NULL { }(Hint: it does not print zero bytes)null structures and classes are probably quite rare in reality, I just found it interesting that I got different {} results: gdc:That's odd. g++ produces different sized objects just from switching 'struct' with 'class'? Good to know, I suppose. Seanstruct: 4 class: 1g++:struct: 1 class: 4
Dec 05 2004