Thread overview
Does D provide automatic dereferencing for accessing members through pointers?
Aug 27, 2014
Gary Willoughby
Aug 27, 2014
Brian Schott
Aug 27, 2014
Gary Willoughby
Aug 28, 2014
Jesse Phillips
Aug 29, 2014
H. S. Teoh
Aug 29, 2014
Andrew Godfrey
Aug 29, 2014
H. S. Teoh
Aug 29, 2014
Andrew Godfrey
Aug 29, 2014
H. S. Teoh
Aug 29, 2014
Ali Çehreli
August 27, 2014
This is something that has been on my mind since i discovered this the other day. Does D provide automatic dereferencing for accessing members through pointers?

Here's an example:

import core.stdc.stdlib : malloc, free;

struct Foo
{
	public int bar;
}

void main(string[] args)
{
	auto foo = cast(Foo*)malloc(Foo.sizeof);

	foo.bar = 42;

	// Dereference the struct before accessing members.
	assert((*foo).bar == 42);

	// No dereferencing! eh?
	assert(foo.bar == 42);

	free(foo);
}

I've taken a look in the std lib and the second form is used a lot. Why don't you need to dereference the pointer 'foo' to reach its member 'bar'?
August 27, 2014
On Wednesday, 27 August 2014 at 19:25:42 UTC, Gary Willoughby wrote:
> Why don't you need to dereference the pointer 'foo' to reach its member 'bar'?

The compiler inserts the dereference for you. (It knows which types are references and which are values and can do this correctly) This makes the syntax consistent between value and reference types.

August 27, 2014
On Wednesday, 27 August 2014 at 19:36:08 UTC, Brian Schott wrote:
> On Wednesday, 27 August 2014 at 19:25:42 UTC, Gary Willoughby wrote:
>> Why don't you need to dereference the pointer 'foo' to reach its member 'bar'?
>
> The compiler inserts the dereference for you. (It knows which types are references and which are values and can do this correctly) This makes the syntax consistent between value and reference types.

Awesome. Ta.
August 28, 2014
On Wednesday, 27 August 2014 at 19:25:42 UTC, Gary Willoughby wrote:
> I've taken a look in the std lib and the second form is used a lot. Why don't you need to dereference the pointer 'foo' to reach its member 'bar'?

Walter didn't want "foo->bar" so we have "foo.bar"
August 29, 2014
On Wed, Aug 27, 2014 at 07:25:41PM +0000, Gary Willoughby via Digitalmars-d-learn wrote:
> This is something that has been on my mind since i discovered this the other day. Does D provide automatic dereferencing for accessing members through pointers?
[...]

Yes it does.

This is particularly useful in generic code where you neither know (nor care) if the incoming type was a pointer or not; you can just use the dot notation and the compiler will do the Right Thing(tm). I remember trying to write C++ templates that will work for both pointer and non-pointer types -- it was rather painful due to the distinction between '.' and '->'. In D you just use '.' throughout and it Just Works(tm).


T

-- 
One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"
August 29, 2014
On Friday, 29 August 2014 at 02:10:46 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> In D you just use '.' throughout and it Just > Works(tm).

Unless the property you're accessing is also a pointer property, like
sizeof. Then you have to be careful. The below prints 4 then 8 (on 32-bit):

unittest {
    import core.stdc.stdlib : malloc, free;

    struct Foo
    {
    	public int bar, baz;
    }

    auto foo = cast(Foo*)malloc(Foo.sizeof);

    import std.stdio;
    writeln(foo.sizeof);
    writeln((*foo).sizeof);

    free(foo);
}

Do pointers have any other cases like this besides 'sizeof'?
I couldn't find a list of pointer properties in the docs (whereas I know
where the list of array properties is).
August 29, 2014
On Fri, Aug 29, 2014 at 04:37:37AM +0000, Andrew Godfrey via Digitalmars-d-learn wrote:
> On Friday, 29 August 2014 at 02:10:46 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> >In D you just use '.' throughout and it Just Works(tm).
> 
> Unless the property you're accessing is also a pointer property, like sizeof. Then you have to be careful.

True. Though if you're writing generic code, chances are that what you want is the pointer size rather than the size of the referenced object. You only really get into trouble when you have to explicitly work with pointers.


[...]
> Do pointers have any other cases like this besides 'sizeof'?
> I couldn't find a list of pointer properties in the docs (whereas I
> know where the list of array properties is).

Probably here?

	http://dlang.org/property.html


T

-- 
Time flies like an arrow. Fruit flies like a banana.
August 29, 2014
On Friday, 29 August 2014 at 05:05:55 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> On Fri, Aug 29, 2014 at 04:37:37AM +0000, Andrew Godfrey via Digitalmars-d-learn wrote:
>> Unless the property you're accessing is also a pointer property, like
>> sizeof. Then you have to be careful.
>
> True. Though if you're writing generic code, chances are that what you
> want is the pointer size rather than the size of the referenced object.
> You only really get into trouble when you have to explicitly work with
> pointers.

Thanks for the link.
'sizeof' is not so bad anyway because it's a property of the type.
It would be worse if pointers had properties.

If you're insane enough to do the following, then this happens...

struct Foo {
    int bar() { return 10; }
}

int bar(Foo f) { return 42; }
int bar(Foo *f) { return 43; }
int bar(Foo **f) { return 44; }

unittest {
    Foo foo;
    auto pfoo = &foo;
    assert((*pfoo).bar == 10);
    assert(pfoo.bar == 10);

    auto ppfoo = &pfoo;
    assert(ppfoo.bar == 44);
}
August 29, 2014
On Fri, Aug 29, 2014 at 05:28:12AM +0000, Andrew Godfrey via Digitalmars-d-learn wrote:
> On Friday, 29 August 2014 at 05:05:55 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> >On Fri, Aug 29, 2014 at 04:37:37AM +0000, Andrew Godfrey via Digitalmars-d-learn wrote:
> >>Unless the property you're accessing is also a pointer property, like sizeof. Then you have to be careful.
> >
> >True. Though if you're writing generic code, chances are that what you want is the pointer size rather than the size of the referenced object.  You only really get into trouble when you have to explicitly work with pointers.
> 
> Thanks for the link.
> 'sizeof' is not so bad anyway because it's a property of the type.
> It would be worse if pointers had properties.
[...]

Which *could* happen if you use alias this, which is a common tool for implementing transparent (or, in this case, not-so-transparent) type wrappers:

	struct SmartPtr(T)
	{
		T* _impl;
		alias _impl this;

		@property dumbProperty() { return 1; }
	}

	struct MyObj
	{
		int dumbProperty = 2;
	}

	void func(T)(T t)
	{
		assert(t.dumbProperty == 2); // will fail
	}

	func(SmartPtr!MyObj.init); // oops


T

-- 
BREAKFAST.COM halted...Cereal Port Not Responding. -- YHL
August 29, 2014
On 08/28/2014 09:37 PM, Andrew Godfrey wrote:

> On Friday, 29 August 2014 at 02:10:46 UTC, H. S. Teoh via
> Digitalmars-d-learn wrote:
>> In D you just use '.' throughout and it Just > Works(tm).
>
> Unless the property you're accessing is also a pointer property, like
> sizeof. Then you have to be careful.

The same applies to class variables. .sizeof and .alignof operate on the class variable. To get the object's size and alignment, one needs to reach for classInstanceSize and classInstanceAlignment.

Unfortunately, for historical reasons they have dissimilar syntax:

import std.string;

class C
{
    ubyte[42] a;
}

void main()
{
    auto c = new C();

    pragma(msg, format("size     : %s vs %s", c.sizeof,
                       __traits(classInstanceSize, C)));

    import std.traits;
    pragma(msg, format("alignment: %s vs %s", c.alignof,
                       classInstanceAlignment!C));
}

Ali