Does .NET make any guarantees that .NET byte arrays are always properly aligned? I do need this to treat e.g. a byte array in unsafe context as longs in x64 to modify chunks of data with the native register size.
But so far I have not found any documentation that the CLR does give me any guarantees that my memory access is then properly aligned.
No. And in fact arrays can be mis-aligned for the x86 jitter. Particularly a problem with double[] and long[], the garbage collector only provides a guarantee that they will be aligned at 4. Which explains the special rule for double[], such an array will be allocated in the Large Object Heap when it has 1000 or more elements. Considerably less than the normal rule for LOH allocations, 85000 or more bytes. The LOH depends on Windows heap alignment guarantees, aligned at 8. This is not otherwise a problem in the x64 jitter.
Getting a bit more specific to your question: byte arrays can never be a problem. A byte is always aligned, no matter where the array starts. A "long" in unmanaged code compiled with the Microsoft compiler is not a problem either, it is 4 bytes so always aligns happily with the default GC alignment rules. It is still 4 bytes in x64 mode so no problem there either.
In .NET objects (of which arrays are a species) are always aligned based on pointer size (e.g. 4 byte or 8 byte alignment). So, object pointers and object arrays are always aligned in .NET.
I should also point out that dereferencing a pointer in .NET doesn't require alignment. However, it will be slower. e.g. if you have a valid byte* pointer and that points to data that is at least eight bytes in length, you can cast it to long* and get the value:
unsafe
{
var data = new byte[ 16 ];
fixed ( byte* dataP = data )
{
var misalignedlongP = ( long* ) ( dataP + 3 );
long value = *misalignedlongP;
}
}
Reading through .NET's source code, you can see that Microsoft sometimes accounts for alignment and often does not. An example would be the internal System.Buffer.Memmove
method (see https://referencesource.microsoft.com/#mscorlib/system/buffer.cs,c2ca91c0d34a8f86). That method has code paths that cast the byte* to long without any alignment checks in a few places, and the calling methods do not check alignment either.