For the purpose of learning I recently looked at an existing assembly (using Reflector) that uses Win32 WriteFile. The implementation is:
Write(IntPtr handleFile, void* bufferData, uint length){
void* buffer = bufferData
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, buffer, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
// This does not compile, because of the cast but also simply because void* does not have += operators (it is unknown size).
buffer += (void*)wrtn;
len -= wrtn;
}
}
It is actually the last 2 lines that are problematic... For one, the compiler complains that you cannot cast uint to void*. Additionally, it is just not possible to use += or even + on void* because it is not of known size.
Write(IntPtr handleFile, void* bufferData, uint length){
byte* buffer = (byte*)bufferData
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, (void*)buffer, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
// This works! I can add to a byte*
buffer = buffer + wrtn; // I could also have used buffer += wrtn
len -= wrtn;
}
}
The above code does work but still the last few lines will compile to:
buffer += (byte*)wrtn;
I do not understand why and very much would like to know why the compiler behaves in this way:
Well for your second point, void* has no size information so the compiler doesn't know how much to increment the pointer by. Should it increment by sizeof(double)? Only with type information does it know what to expect.
Edit: Actually this applies to your first point as well. The compiler needs to know the size of the data type its incrementing. Void* has no size information present so by casting to a byte* you let the compiler know that it needs to increment the pointer by sizeof(byte) * wrtn.
Edit2: With your clarification, it appears you're asking why the Reflector emits code as a void* instead of as it's properly casted type (byte *). Most likely this is due to the type information being extracted from the parameter type and somewhat naively being used in the method. This is probably an issue with Reflector more than the compiler.
It's also possible that this pointer code loses it's type information in the IL, I haven't tested it yet, but it may not carry typing information (besides the size of the data) into the IL for the Reflector to properly emit (normal 'safe' IL should always have this type information). If this was the case Reflector may default to void* or the nearest inferred type.