2010-03-30 37 views
7

Chương trình sau C++ biên dịch và chạy như mong đợi:Con trỏ trong C# để tạo mảng 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(); 
} 

Gần nhất C# ví dụ đơn giản tôi có thể làm cho câu hỏi này là:

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

Vì vậy, làm thế nào để làm cho con trỏ?

+1

tự hỏi tại sao bạn muốn thao tác trực tiếp con trỏ bằng ngôn ngữ được quản lý. – BlackICE

+8

Bởi vì tôi chán: D – y2k

+3

Làm giảm bớt sự nhàm chán của bạn bằng cách đọc chương 18 của đặc điểm kỹ thuật - hai lần - trước khi bạn cố gắng viết mã không an toàn trong C#. –

Trả lời

27

C# không phải là C++ - không mong đợi những điều tương tự để làm việc trong C# hoạt động trong C++. Đó là một ngôn ngữ khác, với một số cảm hứng trong cú pháp.

Trong C++, truy cập mảng là một tay ngắn cho thao tác con trỏ. Đó là lý do tại sao những điều sau đây giống nhau:

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

Tuy nhiên, điều này không đúng trong C#. 5[test] không hợp lệ C# vì không có thuộc tính chỉ mục trên System.Int32.

Trong C#, bạn rất hiếm khi muốn xử lý các con trỏ. Bạn nên chỉ xử lý nó như một mảng int trực tiếp:

int[] test = new int[10]; 

Nếu bạn thực sự muốn để đối phó với con trỏ toán đối với một số lý do, bạn cần phải cờ phương pháp của bạn unsafe, và đặt nó vào một fixed context. Điều này sẽ không được điển hình trong C#, và thực sự có thể là một cái gì đó hoàn toàn không cần thiết.

Nếu bạn thực sự muốn làm công việc này, gần nhất bạn có thể làm trong C# sẽ là:

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

(Một lần nữa, điều này thực sự kỳ lạ C# - không phải cái gì tôi khuyên bạn nên ...)

+1

Cảm ơn bạn đã nghĩ ra câu trả lời. Tôi chỉ cố gắng xem liệu C# có khả năng quản lý bộ nhớ mức thấp như vậy không. Về cơ bản những gì bạn đang nói là loại lập chỉ mục không thể được thực hiện? Tôi không thể có được bất cứ điều gì để làm việc ngay cả khi sử dụng bối cảnh cố định. Bạn có biết nếu chúng ta hoàn toàn bị mắc kẹt bằng cách sử dụng Int32, là ngay cả một loại bản địa hoặc trừu tượng? – y2k

+0

@Joshua: Tôi đã chỉnh sửa câu trả lời của mình để chỉ cho bạn cách bạn có thể thực sự làm điều đó - nhưng tôi thực sự không khuyến nghị nó –

+0

Trên nền tảng C# chạy trên, System.Int32 là kiểu int tự nhiên. Tuy nhiên, dưới int mui xe [] là cùng một khối bộ nhớ mà bạn nhìn thấy trong C++. Nếu bạn làm 'test [5]', dưới mui xe CLR sẽ thực hiện kiểm tra giới hạn theo sau là số học con trỏ và một dereference.Bạn không mất bất kỳ thao tác ở mức độ thấp nào trong trường hợp này. –

5

Bạn cần phải ghim mảng bằng cách sử dụng từ khóa fixed vì vậy nó sẽ không bị cảm động bởi GC:

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

Tuy nhiên, mã không an toàn trong C# là hơn ngoại trừ so với quy định. Tôi sẽ cố gắng dịch mã C của bạn sang mã C# không an toàn.

+2

Lưu ý: Sử dụng cố định trên các biến không nên được thực hiện với lý do chính đáng vì nó làm cho công việc cho GC khó hơn ... và bạn có thể hết bộ nhớ ngay cả khi bạn không sử dụng tất cả bộ nhớ (phân mảnh bộ nhớ). . – Peter

0

Bạn cần tìm hiểu ngôn ngữ C#. Mặc dù có những điểm tương đồng về cú pháp với C/C++, nó giống như Java - có một cách tiếp cận rất khác.

Trong C#, đối tượng hoạt động, theo mặc định, làm tham chiếu. Tức là, bạn không phải chỉ định tham chiếu con trỏ (&) và cú pháp dereferencing (*).

Các vấn đề liên quan