2010-03-30 15 views
7

aşağıdaki C++ program derler ve beklendiği gibi çalışır: Bu soru için yapabilirizİşaretçiler?

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

en yakın C# basit bir örnek:

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

Peki nasıl işaretçi yapabilirim?

+1

İşaretçiyi neden yönetilen bir dilde doğrudan yönlendirmek istediğinizi kendinize sorun. – BlackICE

+8

Çünkü sıkıldım: D – y2k

+3

C# 'da güvensiz kod yazmayı denemeden önce, belirtimin 18. bölümünü okuyarak sıkıntılarınızı hafifletin. –

cevap

27

C# C++ değil - C++ 'da çalışan C# ile aynı şeyleri beklemeyin. Bu sözdiziminde biraz ilham veren farklı bir dil.

C++ uygulamasında dizi erişimi, işaretçi yönlendirmesi için kısa bir eldir. Bu nedenle aşağıdakiler aynıdır: Bu, C# içinde doğru değildir. System.Int32'de dizinleyici özelliği olmadığından, 5[test] geçerli C# değil.

C# içinde, çok nadiren işaretçilerle ilgilenmek istersiniz. Sadece doğrudan bir int dizisi olarak ele daha iyi olur: Eğer gerçekten nedense işaretçi matematik ele almak istiyoruz yoksa

int[] test = new int[10]; 

, işaretlemeye yönteminizi unsafe gerekiyor ve bir fixed context koydu. Bu C# 'de tipik olmayacak ve muhtemelen tamamen gereksiz bir şey. Gerçekten bu işi yapmak istiyorsanız

, C# yapabileceğiniz en yakın olacaktır:

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

(Yine, bu gerçekten garip C# - ı tavsiye ederim bir şey değil ...)

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

Ancak C# güvensiz kod kuraldan çok istisna şudur: GC ile taşınır olmayacak şekilde

+1

İyi düşünülmüş yanıt için teşekkürler. Sadece C# 'nin düşük seviyeli bellek yönetimine sahip olup olmadığını görmeye çalışıyordum. Temel olarak söylediğin şey bu tip bir endeksleme yapılamıyor mu? Sabit bağlamı kullanarak bile çalışmak için hiçbir şey alamıyorum. Int32 kullanarak tamamen sıkışıp kalmayacağımızı biliyor musunuz, bu bir yerli tip mi yoksa bir soyutlama mı? – y2k

+0

@Joshua: Gerçekte nasıl yapabileceğinizi göstermek için cevabımı düzenledim - ama gerçekten önermiyorum –

+0

C# platformları üzerinde çalışır, System.Int32 yerel int türüdür. Ama başlık altında [] C++ 'da gördüğünüz aynı hafıza bloğu. Eğer testi [5] yaparsanız, kaputun altında CLR bir işaret kontrolü gerçekleştirir, ardından işaret aritmetiği ve bir dereferans yapar.Bu durumda düşük seviyeli bir manipülasyon kaybetmiyorsunuz. –

5

Sen fixed anahtar kelime kullanarak diziyi pin gerekir. C kodunuzu güvensiz C# koduna çevirmeyi denerdim.

+2

Not: Sabit değişkenleri kullanmak, GC için işi daha zor hale getirdiği için iyi bir nedenden dolayı yapılmamalıdır ... ve tüm belleği (bellek birleştirme) kullanmasanız da hafızanız bitebilir. . – Peter

0

C# dilini öğrenmeniz gerekiyor. C/C++ ile sözdizimsel benzerlikler olsa da, Java gibi - çok farklı bir yaklaşıma sahiptir.

C# içinde nesneler varsayılan olarak başvuru olarak davranır. Yani, işaretçi başvurusunu (&) ve dereferencing (*) sözdizimini belirtmeniz gerekmez.

İlgili konular