2010-03-30 16 views
7

Il seguente programma C++ compila e viene eseguito come previsto:Puntatori in C# per creare array int?

#include <stdio.h> 

int main(int argc, char* argv[]) 
{ 
    int* test = new int[10]; 

    for (int i = 0; i < 10; i++) 
      test[i] = i * 10; 

    printf("%d \n", test[5]); // 50 
    printf("%d \n", 5[test]); // 50 

    return getchar(); 
} 

Il C# semplice esempio più vicino ho potuto fare a questa domanda è:

using System; 

class Program 
{ 
    unsafe static int Main(string[] args) 
    { 
     // error CS0029: Cannot implicitly convert type 'int[]' to 'int*' 
     int* test = new int[10]; 

     for (int i = 0; i < 10; i++) 
      test[i] = i * 10; 

     Console.WriteLine(test[5]); // 50 
     Console.WriteLine(5[test]); // Error 

     return (int)Console.ReadKey().Key; 
    } 
} 

Quindi, come faccio a fare il puntatore?

+1

chiediti perché vuoi manipolare i puntatori direttamente in un linguaggio gestito. – BlackICE

+8

Perché sono annoiato: D – y2k

+3

Allevia la tua noia leggendo il capitolo 18 delle specifiche - due volte - prima di provare a scrivere codice non sicuro in C#. –

risposta

27

C# non è C++ - non aspettatevi che le stesse cose funzionino in C# che ha funzionato in C++. È una lingua diversa, con qualche ispirazione nella sintassi.

In C++, l'accesso alla matrice è una mano corta per la manipolazione del puntatore. È per questo che i seguenti sono gli stessi:

test[5] 
*(test+5) 
*(5+test) 
5[test] 

Tuttavia, questo non è vero in C#. 5[test] non è valido C#, poiché non è presente la proprietà dell'indicizzatore su System.Int32.

In C#, molto raramente si vuole trattare con i puntatori. Sei meglio solo trattandolo come un array int direttamente:

int[] test = new int[10]; 

Se davvero si vuole fare con la matematica puntatore per qualche motivo, è necessario il metodo di bandiera unsafe, e metterlo in un fixed context. Questo non sarebbe tipico in C#, ed è davvero probabilmente qualcosa di completamente inutile.

Se davvero si vuole fare questo lavoro, il più vicino si può fare in C# sarebbe:

using System; 

class Program 
{ 
    unsafe static int Main(string[] args) 
    { 
     fixed (int* test = new int[10]) 
     { 

      for (int i = 0; i < 10; i++) 
       test[i] = i * 10; 

      Console.WriteLine(test[5]); // 50 
      Console.WriteLine(*(5+test)); // Works with this syntax 
     } 

     return (int)Console.ReadKey().Key; 
    } 
} 

(Ancora una volta, questo è davvero strano C# - non qualcosa mi consiglia ...)

+1

Grazie per la risposta ben ponderata. Stavo solo cercando di capire se C# fosse capace di una gestione della memoria di così basso livello. Fondamentalmente quello che stai dicendo è che quel tipo di indicizzazione non può essere fatto? Non riesco a far funzionare nulla nemmeno usando il contesto fisso. Sai se siamo completamente bloccati con Int32, è anche un tipo nativo o un'astrazione? – y2k

+0

@Joshua: ho modificato la mia risposta per mostrarti come puoi farlo davvero, ma non lo consiglio vivamente. –

+0

Sulle piattaforme in cui C# viene eseguito, System.Int32 è il tipo nativo int. Ma sotto il cappuccio int [] è lo stesso blocco di memoria che si vede in C++. Se esegui 'test [5]', sotto il cofano il CLR eseguirà un controllo dei limiti seguito da aritmetica del puntatore e dereferenziazione.In questo caso, non stai perdendo alcuna manipolazione di basso livello. –

5

è necessario appuntare la matrice utilizzando la parola chiave fixed in modo da non ottenere mosso dalla GC:

fixed (int* test = new int[10]) 
{ 
    // ... 
} 

Tuttavia, codice unsafe in C# è più l'eccezione che la regola. Proverò a tradurre il tuo codice C in codice C# non sicuro.

+2

Nota: l'uso di variabili fisse su variabili non deve essere eseguito senza una buona ragione, poiché rende più difficile il lavoro per il GC ... e la memoria può esaurirsi anche se non si utilizza tutta la memoria (deframmentazione della memoria). . – Peter

0

È necessario imparare il linguaggio C#. Sebbene ci siano somiglianze sintattiche con C/C++, esso - come Java - ha un approccio molto diverso.

In C#, gli oggetti si comportano, come impostazione predefinita, come riferimenti. Cioè, non è necessario specificare la sintassi di riferimento (&) e la sintassi di dereferenziazione (*).