2010-03-30 7 views
7

Das folgende C++ Programm kompiliert und läuft wie erwartet:Zeiger in C#, um int Array zu machen?

#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(); 
} 

Das nächstgelegene C# einfache Beispiel ich für diese Frage stellen könnte, ist:

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

So wie ich den Zeiger machen?

+1

Fragen Sie sich, warum Sie Zeiger direkt in einer verwalteten Sprache manipulieren möchten. – BlackICE

+8

Weil mir langweilig ist: D – y2k

+3

Mildern Sie Ihre Langeweile, indem Sie Kapitel 18 der Spezifikation zweimal lesen, bevor Sie versuchen, unsicheren Code in C# zu schreiben. –

Antwort

27

C# ist nicht C++ - erwarten Sie nicht, dass die gleichen Dinge in C# funktionieren, die in C++ funktionierten. Es ist eine andere Sprache, mit etwas Inspiration in der Syntax.

In C++ ist Arrayzugriff eine kurze Hand für Zeigermanipulation. Deshalb sind die folgenden gleich:

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

Dies ist jedoch in C# nicht wahr. 5[test] ist nicht gültig C#, da es keine Indexereigenschaft auf System.Int32 gibt.

In C# möchten Sie sehr selten mit Zeigern umgehen. Du bist besser dran, nur es als int Array Behandlung direkt:

int[] test = new int[10]; 

Wenn Sie wirklich aus irgendeinem Grund mit Zeiger Mathematik beschäftigen wollen, die Sie benötigen, um Ihre Flagge Methode unsafe, und steckte es in eine fixed context. Dies wäre in C# nicht typisch und ist wahrscheinlich etwas völlig Unnötiges.

Wenn Sie wirklich diese Arbeit machen wollen, in der Nähe Sie in C# tun wäre:

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

(Auch dies ist wirklich seltsam C# - nicht etwas, was ich empfehlen würde ...)

+1

Danke für die gut durchdachte Antwort. Ich habe nur versucht zu sehen, ob C# zu einem solchen Low-Level-Speichermanagement fähig ist. Grundsätzlich, was Sie sagen, ist diese Art der Indizierung nicht möglich? Ich kann nichts erreichen, selbst wenn ich den festen Kontext verwende. Weißt du, ob wir mit Int32 völlig festgefahren sind, ist das überhaupt ein nativer Typ oder eine Abstraktion? – y2k

+0

@Joshua: Ich habe meine Antwort bearbeitet, um Ihnen zu zeigen, wie Sie es tatsächlich tun können - aber ich kann es wirklich nicht empfehlen –

+0

Auf den Plattformen läuft C#, System.Int32 ist der native Int-Typ. Aber unter der Haube ist int [] derselbe Speicherblock, den Sie in C++ sehen. Wenn Sie "test [5]" testen, führt die CLR unter der Haube eine Grenzwertüberprüfung durch, gefolgt von Zeigerarithmetik und einer Dereferenzierung.Sie verlieren in diesem Fall keine Low-Level-Manipulation. –

5

Sie benötigen das Array mit dem fixed Stichwort zu, damit es nicht durch die GC bewegt wird erhalten:

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

jedoch unsicherer Code in C# die Ausnahme als die Regel ist mehr. Ich würde versuchen, Ihren C-Code in nicht-unsicheren C# -Code zu übersetzen.

+2

Hinweis: Die Verwendung von festen Variablen sollte nicht ohne Grund erfolgen, da dies den Job für den GC schwieriger macht ... und Sie können nicht genügend Arbeitsspeicher haben, auch wenn Sie nicht den gesamten Arbeitsspeicher verwenden (Speicherdefragmentierung). . – Peter

0

Sie müssen die C# -Sprache lernen. Obwohl es syntaktische Ähnlichkeiten zu C/C++ gibt, hat es - wie Java - einen ganz anderen Ansatz.

In C# verhalten sich Objekte standardmäßig als Referenzen. Das heißt, Sie müssen keine Pointer-Referenzierung (&) und Dereferenzierung (*) -Syntax angeben.