I have some unsafe C# code that does pointer arithmetic on large blocks of memory on type byte*
, running on a 64-bit machine. It works correctly most of the tim
It's a C# compiler bug (filed on Connect). @Grant has shown that the MSIL generated by the C# compiler interprets the uint
operand as signed. That's wrong according to the C# spec, here's the relevant section (18.5.6):
18.5.6 Pointer arithmetic
In an unsafe context, the
+
and-
operators (§7.8.4 and §7.8.5) can be applied to values of all pointer types exceptvoid*
. Thus, for every pointer typeT*
, the following operators are implicitly defined:T* operator +(T* x, int y); T* operator +(T* x, uint y); T* operator +(T* x, long y); T* operator +(T* x, ulong y); T* operator +(int x, T* y); T* operator +(uint x, T* y); T* operator +(long x, T* y); T* operator +(ulong x, T* y); T* operator –(T* x, int y); T* operator –(T* x, uint y); T* operator –(T* x, long y); T* operator –(T* x, ulong y); long operator –(T* x, T* y);
Given an expression
P
of a pointer typeT*
and an expressionN
of typeint
,uint
,long
, orulong
, the expressionsP + N
andN + P
compute the pointer value of typeT*
that results from addingN * sizeof(T)
to the address given byP
. Likewise, the expressionP - N
computes the pointer value of typeT*
that results from subtractingN * sizeof(T)
from the address given byP
.Given two expressions,
P
andQ
, of a pointer typeT*
, the expressionP – Q
computes the difference between the addresses given byP
andQ
and then divides that difference bysizeof(T)
. The type of the result is alwayslong
. In effect,P - Q
is computed as((long)(P) - (long)(Q)) / sizeof(T)
.If a pointer arithmetic operation overflows the domain of the pointer type, the result is truncated in an implementation-defined fashion, but no exceptions are produced.
You're allowed to add a uint
to a pointer, no implicit conversion takes place. And the operation does not overflow the domain of the pointer type. So truncation is not allowed.