Domanda

Ai fini della formazione di recente ho guardato un assieme esistente (utilizzando Reflector) che utilizza Win32 WriteFile. L'implementazione è:

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;
}

}

Si tratta in realtà le ultime 2 righe che sono problematici ... Per uno, il compilatore si lamenta che non puoi lanciare uint a void *. Inoltre, non solo è possibile utilizzare + = o anche + sul void *, perché non è noto dimensioni.

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;
    }
}

Il codice sopra funziona, ma ancora le ultime righe verrà compilato a:

buffer += (byte*)wrtn;

Non capisco perché e molto vorrei sapere il motivo per cui il compilatore si comporta in questo modo:

  1. Perché non genera il cast come questo (e perché non viene accettato di fare questo nel codice utente scritto)?
  2. Ciò che è al passo con i + = operatori void * nel primo esempio? Quale codice codice originale hanno generato tampone + = (void *) wrtn dove buffer è anche void * ????
È stato utile?

Soluzione

Bene per il tuo secondo punto, void * non ha informazioni dimensioni in modo che il compilatore non sa quanto per incrementare il puntatore. Dovrebbe incrementare di sizeof (doppia)? Solo con le informazioni di tipo fa a sapere cosa aspettarsi.

Modifica: In realtà questo vale per il primo punto pure. Il compilatore ha bisogno di conoscere le dimensioni del tipo di dati propria di incremento. Void * non ha informazioni attuali dimensioni in modo da lanciare ad un byte * si lascia che il compilatore sa che ha bisogno di incrementare il puntatore per sizeof (byte) * wrtn.

Edit2: Con il vostro chiarimento, sembra che stai chiedendo il motivo per cui il riflettore emette codice come un vuoto * invece di tipo come è correttamente colato (byte *). Molto probabilmente questo è dovuto al tipo di informazioni viene estratto dal tipo di parametro e un po 'ingenuamente di essere utilizzato nel metodo. Questo è probabilmente un problema con il riflettore più che il compilatore.

E 'anche possibile che questo codice puntatore perde è digitare le informazioni in IL, non l'ho ancora provato, ma non può trasportare le informazioni digitando (oltre alla dimensione dei dati) nella IL per il riflettore di emettere correttamente (normale iL 'sicuro' deve sempre avere queste informazioni tipo). Se questo fosse il caso riflettore può predefinito di annullare * o il tipo inferito più vicino.

Altri suggerimenti

  

Ai fini della formazione di recente ho guardato un assieme esistente (utilizzando Reflector)

L'unico problema qui sta usando riflettore - a quanto pare, non è così bravo a dedurre il codice originale C # da IL. L'IL sé è corretta, e non ha calchi (nessuno sono necessari - in IL, si preme un puntatore e un argomento intero sullo stack, e fare un add / sottrazione). Riflettore è sbagliato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top