2010-03-30 14 views
7

El siguiente programa en C++ compila y ejecuta como se esperaba:Punteros en C# para hacer una matriz 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(); 
} 

El simple ejemplo más cercano de C# que podría hacer de esta pregunta es:

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

Entonces, ¿cómo hago para quitar el puntero?

+1

pregúntese por qué quiere manipular punteros directamente en un lenguaje administrado. – BlackICE

+8

Porque estoy aburrido: D – y2k

+3

Alivie su aburrimiento leyendo el capítulo 18 de la especificación, dos veces, antes de intentar escribir un código inseguro en C#. –

Respuesta

27

C# no es C++ - no espere que las mismas cosas funcionen en C# que funcionó en C++. Es un lenguaje diferente, con cierta inspiración en la sintaxis.

En C++, el acceso a la matriz es una forma abreviada de manipular el puntero. Es por eso que los siguientes son los mismos:

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

Sin embargo, esto no es cierto en C#. 5[test] no es válido C#, ya que no hay propiedad del indexador en System.Int32.

En C#, muy rara vez quiere tratar con punteros. Es mejor que simplemente tratándolo como una matriz int directamente:

int[] test = new int[10]; 

Si realmente quiere tratar con las matemáticas puntero por alguna razón, es necesario bandera de su método de unsafe, y lo puso en un fixed context. Esto no sería típico en C#, y probablemente sea algo completamente innecesario.

Si realmente quiere hacer este trabajo, el más cercano que se puede hacer en C# sería:

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

(De nuevo, esto es muy raro C# - no es algo que recomiendo ...)

+1

Gracias por la respuesta bien pensada. Solo estaba tratando de ver si C# era capaz de administrar una memoria de bajo nivel. Básicamente lo que estás diciendo es que ese tipo de indexación no se puede hacer? No puedo hacer que nada funcione incluso usando el contexto fijo. ¿Sabes si estamos completamente trabajados usando Int32, es eso incluso un tipo nativo o una abstracción? – y2k

+0

@Joshua: Edité mi respuesta para mostrarle cómo puede hacerlo, pero realmente no lo recomiendo –

+0

En las plataformas en las que se ejecuta C#, System.Int32 es el tipo int nativo. Pero bajo el capó int [] es el mismo bloque de memoria que se ve en C++. Si haces 'test [5]', bajo el capó, el CLR hará una comprobación de límites seguida por una aritmética de puntero y una desreferencia.No estás perdiendo ninguna manipulación de bajo nivel en este caso. –

5

Necesitas ponerle la matriz usando la palabra clave fixed para que no se desplace de la GC:

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

sin embargo, el código no seguro en C# es más la excepción que la regla. Intentaría traducir tu código C al código C# no inseguro.

+2

Nota: El uso de variables fijas no debería realizarse sin una buena razón, ya que dificulta el trabajo del GC ... y puede quedarse sin memoria incluso si no usa toda la memoria (desfragmentación de memoria). . – Peter

0

Necesita aprender el lenguaje C#. Aunque hay similitudes sintácticas con C/C++, - como Java - tiene un enfoque muy diferente.

En C#, los objetos se comportan, por defecto, como referencias. Es decir, no tiene que especificar la referencia del puntero (&) y la sinferencia de desreferencia (*).