Struct Union behavior

Nicholas Wilson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jan 6 04:25:31 PST 2016


On Wednesday, 6 January 2016 at 11:39:44 UTC, Voitech wrote:
> Hello, i am new to D language and trying to learn it by coding.
> I compile my programs on Xubuntu 14.04 with DMD64 D Compiler 
> v2.069.2.
> So i have a struct/union which contains two fields representing 
> real and string values:
>
> public union Element
> {
> 	private real _value;
> 	private string _rawValue;
>
> 	@property{
> 		real value(){
> 			return _value;
> 		}
> 		void value(real value){
> 			_value=value;
> 		}
>
> 	}
> 	@property {
> 		ref string rawValue(){
> 			return _rawValue;
> 		}
> 		void rawValue(ref string value){
> 			_rawValue=value;
> 		}
>
> 	}
>
> 	
> 	public Element opBinary(string op)(Element other){
> 		Element newElement;
> 		real value=mixin("this.value "~op~"other.value");
> 		newElement.value=value;
> 		return newElement;
> 	}
>
> 	public bool opEquals(Element other){
> 		if(this.rawValue == null && other.rawValue == null){
> 			return this.opEquals(other.rawValue);
> 		}
> 		return this.opEquals(other.value);
> 	}
> 	public bool opEquals(real value){
> 		return this.value==value;
> 	}
> 	public bool opEquals(string rawValue){
> 		return this.rawValue==rawValue;
> 	}
>
> 	unittest{
> 		Element e1 = {4},e2 ={5};
> 		writeln("e1 is at address: ",&e1);
> 		writeln("e2 is at address: ",&e2);
> 		writeln("e1.value is at address: ",&e1._value);
> 		writeln("e2.value is at address: ",&e2._value);
> 		assert(e1+e2==9);
> 	}
>
> 	unittest{
> 		Element s1={_rawValue:"+"},s2,s3,s4;
> 		writeln("s1 is at address: ",&s1);
> 		writeln("s2 is at address: ",&s2);
> 		writeln("s3 is at address: ",&s3);
> 		writeln("s1.value is at address: ",&s1._value);
> 		writeln("s2.value is at address: ",&s2._value);
> 		writeln("s3.value is at address: ",&s3._value);
> 		writeln("s4.value is at address: ",&s4._value);
> 		writeln("s1.rawValue ",s1._rawValue);
> 		writeln("s1.value: ",s1._value);
> 		writeln("s2.value: ",s2._value);
> 		writeln("s3.value: ",s3._value);
> 		writeln("s4.value: ",s4._value );
> 		assert(s1!=s2);
> 	}
> }
>
> The unit test results are:
>
> e1 is at address: 7FFCEFBA7510
> e2 is at address: 7FFCEFBA7520
> e1.value is at address: 7FFCEFBA7510
> e2.value is at address: 7FFCEFBA7520
> s1 is at address: 7FFCEFBA7500
> s2 is at address: 7FFCEFBA7510
> s3 is at address: 7FFCEFBA7520
> s1.value is at address: 7FFCEFBA7500
> s2.value is at address: 7FFCEFBA7510
> s3.value is at address: 7FFCEFBA7520
> s4.value is at address: 7FFCEFBA7530
> s1.rawValue +
> s1.value: 0.125
> s2.value: 4
> s3.value: 5
> s4.value: 9
>
> Can anyone tell me why s2,s3,s4 have initialized _value field?  
> Shouldn't it be collected by GC when first unit test (with 
> e1,e2) finishes ? If not how to handle this behavior, to use 
> union without preinitialized fields.

Probably because you are accessing uninitialised memory. the 
values 4,5,9 appear in the first unittest and are left on the 
stack. Unions ,unlike structs, do not initialise their fields 
because it does not make sense to do so because the memory 
aliases. This can be observed by looking at the size of element 
(16 bytes) which is less than the size of an array (on 64 bit 
systems) , 2*8 bytes plus size of a real (8 or 10 bytes (x86/64)).

other things unrelated to your question. Things are public by 
default so the 'public's are redundant. strings are arrays so 
(most of the time) don't need ref, as the elements are accessed 
through a pointer.

See also Algebraic for cases (most) when you want to know the 
type of the value of the union.

Comparisons to null should use 'is' expressions

Having _value and _rawvalue as private and then providing getters 
and setters is redundant. the same behaviour can be achieved by 
making the public. getters and setters are for either heaving 
only a getter or calling a function when a field is changed (e.g. 
updating a cache)

Nic


More information about the Digitalmars-d-learn mailing list