Для изучения я недавно посмотрел на существующую сборку (используя Reflector), которая использует Win32 WriteFile. Реализация:указатель арифметики и компилятор C#
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;
}
}
Это на самом деле последние 2 строки, которые являются проблематичными ... Для одного, компилятор жалуется, что вы не можете бросить UINT аннулировать *. Кроме того, просто невозможно использовать + = или даже + на void *, потому что это не известный размер.
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;
}
}
Приведенный выше код работает, но до сих пор последние несколько строк будет компилировать:
buffer += (byte*)wrtn;
Я не понимаю, почему и очень хотелось бы знать, почему компилятор ведет себя таким образом:
- Почему он генерирует приведение как это (и почему это не принято делать это в написанном пользователем коде)?
- Что происходит с операторами + = на void * в первом примере? Какой исходный кодовый код сгенерировал буфер + = (void *) wrtn, где буфер также недействителен * ????
Спасибо за ответ, но, как я уже указывал в своем оригинальном посте, я знаю о всей вещи «неизвестного» размера. Меня удивляет то, что компилятор все равно каким-то образом генерирует void * somepointer + = (void *) uint wrtn (я добавил тип для ясности). Это не должно быть возможным (и, конечно же, не компилируется!), Поэтому мне интересно, какой исходный код был сгенерирован этим ... – Kris
Так что это скорее всего отражение.В конце концов, задача Reflectors, вероятно, не простая. Я мог понять, как рефлектор выплескивает броски на основе найденного ИЛ, так что часть вопроса, которую я считаю, решена. Тем не менее, я пытался и пытался генерировать вывод отражателя (ради получения проницательности) точно так же, как тот, который был в моем самом первом блоке кода (поэтому без использования байта *), и я просто не могу туда добраться ... Вы не можете сделать много с void *, поэтому мне действительно интересно, как выглядел бы оригинальный код, который сгенерировал это! – Kris
Скорее всего, это была ваша «фиксированная» копия (в пределах некоторого допуска). Вы пытались сбросить IL и отсортировать это вручную? Нетрудно понять, с чем должен работать Reflector, чтобы вы могли видеть, откуда это взялось. –