www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Wrong pointer calculation without casting on struct

reply "tcak" <tcak gmail.com> writes:
I am on 64-bit Linux.

I defined a struct that it 8 bytes in total.

align(1) struct MessageBase{
align(1):
	ushort qc;
	ushort wc;
	ushort id;
	ushort contentLength;
	void[0] content;
}


I defined a function in this struct that tries to set a pointer 
to "contentLength" field.

writeln( "Without: ", (&this + id.offsetof) );
writeln( "With   : ", (cast(size_t)&this + id.offsetof) );

Results:
Without: 7FFFF74F5030
With   : 140737342558228

0x7FFFF74F5030 => 140737342558256


As it is seen, there is 28 bytes of difference between them. What 
is this behaviour exactly?
Feb 05 2015
next sibling parent reply "tcak" <tcak gmail.com> writes:
On Friday, 6 February 2015 at 03:59:51 UTC, tcak wrote:
 I am on 64-bit Linux.

 I defined a struct that it 8 bytes in total.

 align(1) struct MessageBase{
 align(1):
 	ushort qc;
 	ushort wc;
 	ushort id;
 	ushort contentLength;
 	void[0] content;
 }


 I defined a function in this struct that tries to set a pointer 
 to "contentLength" field.

 writeln( "Without: ", (&this + id.offsetof) );
 writeln( "With   : ", (cast(size_t)&this + id.offsetof) );

 Results:
 Without: 7FFFF74F5030
 With   : 140737342558228

 0x7FFFF74F5030 => 140737342558256


 As it is seen, there is 28 bytes of difference between them. 
 What is this behaviour exactly?
By the way, writeln("Base Normal: ", &this); writeln("Base Cast : ", cast(size_t)&this); Result: Base Normal: 7FFFF74F5010 Base Cast : 140737342558224 0x7FFFF74F5010 => 140737342558224 These are same. So, the issue is about addition process.
Feb 05 2015
parent "Baz" <bb.temp gmx.com> writes:
On Friday, 6 February 2015 at 04:10:08 UTC, tcak wrote:
 On Friday, 6 February 2015 at 03:59:51 UTC, tcak wrote:
 I am on 64-bit Linux.

 I defined a struct that it 8 bytes in total.

 align(1) struct MessageBase{
 align(1):
 	ushort qc;
 	ushort wc;
 	ushort id;
 	ushort contentLength;
 	void[0] content;
 }


 I defined a function in this struct that tries to set a 
 pointer to "contentLength" field.

 writeln( "Without: ", (&this + id.offsetof) );
 writeln( "With   : ", (cast(size_t)&this + id.offsetof) );

 Results:
 Without: 7FFFF74F5030
 With   : 140737342558228

 0x7FFFF74F5030 => 140737342558256


 As it is seen, there is 28 bytes of difference between them. 
 What is this behaviour exactly?
By the way, writeln("Base Normal: ", &this); writeln("Base Cast : ", cast(size_t)&this); Result: Base Normal: 7FFFF74F5010 Base Cast : 140737342558224 0x7FFFF74F5010 => 140737342558224 These are same. So, the issue is about addition process.
I've tried this; import std.stdio; struct MessageBase{ align(1): ushort qc; ushort wc; ushort id; ushort contentLength; void[0] content; void a(){ writefln("%.8X",(cast(void*)&this + id.offsetof)); writefln("%.8X",(cast(size_t)&this + id.offsetof)); } } void main() { MessageBase mb; mb.a; } and got the same value for both. Your problem is: typeof(&this).stringof is "MessageBase*" so with ptr arithmetic when you add 1 you actually shift by 1 * MessageBase.sizeof. typeof(cast(void*)&this) is "void*" so with ptr arithmetic you shift by a certain number of bytes.
Feb 05 2015
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/05/2015 07:59 PM, tcak wrote:

 writeln( "Without: ", (&this + id.offsetof) );
In pointer arithmetic, the increment value means "that many *objects* away", not "than many bytes away". Since id.offsetof is 4, you are calculating 4 MessageBase objects away (4*8==32 bytes away).
 writeln( "With   : ", (cast(size_t)&this + id.offsetof) );
That is not pointer arithmetic, so the increment is just 4. 32 - 4 == 28. Ali
Feb 05 2015