Casting pointers

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sat Jul 7 08:00:38 PDT 2007


Henning Hasemann wrote:
> I have the following code:
> 
> import std.stdio;
> 
> interface I { void foo(); }
> 
> class C : I {
>   void foo() { writefln("foo called"); }
> }
> 
> void main() {
>   auto c = new C;
>   I* i = cast(I*)(&c);
>   (*i).foo();
> }
> 
> What I'd expect it to do would be to write "foo called".
> Instead it prints out "icast.C" with dmd-1.018.
> 
> Did I something wrong casting the address of c (which is in fact a
> reference to a reference)? If so shouldnt there be a compiler error?

Yes, you did something wrong. You cast a pointer to an object reference 
to a pointer to an interface reference and expected it to do something 
meaningful. Interfaces use different vtables than objects, so the binary 
representation of the references won't be the same even if they 
reference the same actual object. (Interface pointers point to the 
address of the interface vtable pointer in the object instead of to the 
start of the object (where the class vtable is)).

(What's happening in your program: I.foo() probably occupies the same 
position in the interface vtable as Object.print() does in the class 
vtable. Since you haven't overridden toString() that then prints the 
name of the class; I guess your source file is named icast.d?)

I don't think this should be a compile error since pointer casting is 
technically allowed, but an optional warning might be nice. However, 
pointer-casting is generally a bad idea so the best solution is just to 
avoid it as much as possible.

> Is there any way to have the address of the Variable c interpreted as
> an address to a I-interface at all? I know it works without the address
> stuff but I'd really like to use this pointer-to-reference semantic.

First cast to a C* (or Object*), then dereference it and cast to I.
These'll probably work:
---
     I i = cast(I) *cast(Object*) &c;
// and
     I i = cast(I) *cast(C*) &c;
// though cast(C*) is pretty useless here :)
---
(You can't get a pointer to an interface this way unless you store the 
result of "cast(I) ..." first, since there's no interface reference to 
point to)


By the way, you shouldn't need to use "(*i).whatever"; pointers are 
dereferenced automatically when members are accessed (except when you 
need things like (*i).sizeof because those are also valid properties of 
the pointers themselves).



More information about the Digitalmars-d mailing list