64-bit pointer arithmetic in C#, Check for arithmetic overflow changes behavior

前端 未结 4 2045
攒了一身酷
攒了一身酷 2021-01-06 13:31

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

4条回答
  •  日久生厌
    2021-01-06 13:52

    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 except void*. Thus, for every pointer type T*, 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 type T* and an expression N of type int, uint, long, or ulong, the expressions P + N and N + P compute the pointer value of type T* that results from adding N * sizeof(T) to the address given by P. Likewise, the expression P - N computes the pointer value of type T* that results from subtracting N * sizeof(T) from the address given by P.

    Given two expressions, P and Q, of a pointer type T*, the expression P – Q computes the difference between the addresses given by P and Q and then divides that difference by sizeof(T). The type of the result is always long. 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.

提交回复
热议问题