How ptr arithmitic works??? It doesn't make any sense....

rempas rempas at tutanota.com
Mon Dec 5 14:17:53 UTC 2022


On Sunday, 4 December 2022 at 19:00:15 UTC, H. S. Teoh wrote:
> This is true only if you're talking about pointers in the sense 
> of pointers in assembly language.  Languages like C and D add 
> another layer of abstraction over this.
>
>
>> Another thing with pointers is that it doesn't have "types".
>
> This is where you went wrong.  In assembly language, yes, a 
> pointer value is just a number, and there's no type associated 
> with it. However, experience has shown that manipulating 
> pointers at this raw, untyped level is extremely error-prone.  
> Therefore, in languages like C or D, a pointer *does* have a 
> type.  It's a way of preventing the programmer from making 
> silly mistakes, by associating a type (at compile-time only, of 
> course) to the pointer value.  It's a way of keeping track that 
> address 1234 points to a short, and not to a float, for 
> example.  At the assembly level, of course, this type 
> information is erased, and the pointers are just integer 
> addresses.  However, at compile-type, this type exists to 
> prevent, or at least warn, the programmer from treating the 
> value at the pointed-to address as the wrong type.  This is not 
> only because of data sizes, but the interpretation of data.  A 
> 32-bit value interpreted as an int is completely different from 
> a 32-bit value interpreted as a float, for example.  You 
> wouldn't want to perform integer arithmetic on something that's 
> supposed to be a float; the result would be garbage.
>
> In addition, although in theory memory is byte-addressable, 
> many architectures impose alignment restrictions on values 
> larger than a byte. For example, the CPU may require that 
> 32-bit values (ints or floats) must be aligned to an address 
> that's a multiple of 4 bytes.  If you add 1 to an int* address 
> and try to access the result, it may cause performance issues 
> (the CPU may have to load 2 32-bit values and reassemble parts 
> of them to form the misaligned 32-bit value) or a fault (the 
> CPU may refuse to load a non-aligned address), which could be a 
> silent failure or may cause your program to be forcefully 
> terminated. Therefore, typed pointers like short* and int* may 
> not be entirely an artifact that only exists in the compiler; 
> it may not actually be legal to add a non-aligned value to an 
> int*, depending on the hardware you're running on.
>
> Because of this, C and D implement pointer arithmetic in terms 
> of the underlying value type. I.e., adding 1 to a char* will 
> add 1 to the underlying address, but adding 1 to an int* will 
> add int.sizeof to the underlying address instead of 1. I.e.:
>
> 	int[2] x;
> 	int* p = &x[0];	// let's say this is address 1234
> 	p++;		// p is now 1238, *not* 1235 (int.sizeof == 4)
>
> As a consequence, when you cast a raw pointer value to a typed 
> pointer, you are responsible to respect any underlying 
> alignment requirements that the machine may have. Casting a 
> non-aligned address like 1235 to a possibly-aligned pointer 
> like int* may cause problems if you're not careful.  Also, the 
> value type of the pointer *does* matter; you will get different 
> results depending on the size of the type and any alignment 
> requirements it may have.  Pointer arithmetic involving T* 
> operate in units of T.sizeof, *not* in terms of the raw pointer 
> value.
>
>
> T

Wow! Seriously, thanks a lot for this detailed explanation! I 
want to write a compiler and this type of explanations that not 
only give me the answer but explain me in detail why something 
happens are a gift for me! I wish I could meet you in person and 
buy you a coffee. Maybe one day, you never know! Thanks a lot and 
have an amazing day!


More information about the Digitalmars-d-learn mailing list