Let us assume the following CIL program:
.assembly extern mscorlib {}
.assembly Program {}
.method private static void Main() cil managed
{
.entrypoint
.maxstack 4
.locals init ( int32[] a,
uint32 t )
// Creates an array of int of size 10
ldc.i4 10
newarr int32
stloc.0
// Writes 0xaabbccdd at the index 2 of the array
ldloc.0
ldc.i4.2
ldc.i4 0xaabbccdd
stelem.i4
// Loads
ldloc.0
ldc.i4 9 // <HERE>
ldelem.i1
stloc.1
ldstr "Value: 0x{0:x8}"
ldloc.1
box [mscorlib]System.UInt32
call void [mscorlib]System.Console::WriteLine(string, object)
ret
}
This program:
- creates an array of int size 10
- writes 0xaabbccdd at index 2 of the array
- tries to read one byte in the array using ldelem.i1
- prints the result
The trick is that I use “ldelem.i1” instead of the more standard “idelem.i4” for performance issues (I want to avoid doing masking) The idea is to access to the data of the array the way one does with pointers in C.
But things are not so nice because the program crashes (IndexOutOfRangeException) for indexes of more than 10 as argument for ldelem.i1.
This males the trick useless as I can’t access data after the first half of the integer at the third index.
Ideally, I want to access bytes up to index 39, which corresponds to the last byte of the integer at index 9.
I would very much appreciate if somebody had some ideas on this point.
Interesting. The ECMA-335 states that it will throw an exception if the index is greater than or equal to the size of the array, which it definitely is. What surprises me about this isn’t that the exception is thrown, but that the index is treated as a byte index into an int array in the first place – I can’t see that that’s specified anywhere.
I suspect you’re into the realms of unspecified behaviour, quite possibly behaviour which isn’t intended to be specified – I suspect you’re just not meant to use
ldelem.i1on anintarray.