खोज…
टिप्पणियों
संकेत और unsafe
उनके स्वभाव के कारण, संकेत अयोग्य कोड का उत्पादन करते हैं। इस प्रकार, किसी भी पॉइंटर प्रकार के उपयोग के लिए unsafe
संदर्भ की आवश्यकता होती है।
प्रकार System.IntPtr
एक void*
आसपास एक सुरक्षित आवरण है। यह void*
से अधिक सुविधाजनक विकल्प के रूप में लक्षित है void*
जब एक असुरक्षित संदर्भ को अन्यथा हाथ में कार्य करने की आवश्यकता नहीं होती है।
अपरिभाषित व्यवहार
सी और सी ++ की तरह, पॉइंटर्स का गलत उपयोग अपरिभाषित व्यवहार को लागू कर सकता है, संभावित दुष्प्रभाव स्मृति भ्रष्टाचार और अनपेक्षित कोड के निष्पादन के साथ। अधिकांश पॉइंटर ऑपरेशनों की अपरिवर्तनीय प्रकृति के कारण, पॉइंटर्स का सही उपयोग पूरी तरह से प्रोग्रामर की जिम्मेदारी है।
प्रकार जो संकेत का समर्थन करते हैं
C और C ++ के विपरीत, सभी C # प्रकार में समान सूचक प्रकार नहीं होते हैं। यदि निम्न मानदंड दोनों लागू होते हैं तो एक टाइप T
में एक समान पॉइंटर प्रकार हो सकता है:
-
T
एक स्ट्रक्चर टाइप या पॉइंटर टाइप है। -
T
में केवल सदस्य होते हैं जो इन दोनों मानदंडों को पुनरावर्ती रूप से संतुष्ट करते हैं।
एरे एक्सेस के लिए पॉइंटर्स
यह उदाहरण दर्शाता है कि C # एरेज़ के लिए सी-लाइक एक्सेस के लिए पॉइंटर्स का उपयोग कैसे किया जा सकता है।
unsafe
{
var buffer = new int[1024];
fixed (int* p = &buffer[0])
{
for (var i = 0; i < buffer.Length; i++)
{
*(p + i) = i;
}
}
}
unsafe
कीवर्ड की आवश्यकता है क्योंकि पॉइंटर एक्सेस किसी भी सीमा की जांच का उत्सर्जन नहीं करेगा जो नियमित रूप से सी # एक्सेस करते समय नियमित रूप से उत्सर्जित होते हैं।
fixed
कीवर्ड सी-कंपाइलर को ऑब्जेक्ट को अपवाद-सुरक्षित तरीके से पिन करने के लिए निर्देशों का उत्सर्जन करने के लिए कहता है। यह सुनिश्चित करने के लिए पिनिंग की आवश्यकता है कि कचरा कलेक्टर स्मृति में सरणी को स्थानांतरित नहीं करेगा, क्योंकि यह सरणी के भीतर इंगित करने वाले किसी भी संकेत को अमान्य कर देगा।
सूचक अंकगणित
संकेत और जोड़ में घटाव पूर्णांक से अलग तरीके से काम करता है। जब एक पॉइंटर को बढ़ाया या घटाया जाता है, तो यह पता इस बात की ओर इशारा करता है कि वह रेफ़रेंट प्रकार के आकार से बढ़ा या घटा है।
उदाहरण के लिए, int
(के लिए उर्फ System.Int32
) एक तो 4. के आकार की है int
पता 0 में संग्रहित किया जा सकता है, बाद में int
पता 4 में संग्रहित किया जा सकता है, और इतने पर। कोड में:
var ptr = (int*)IntPtr.Zero;
Console.WriteLine(new IntPtr(ptr)); // prints 0
ptr++;
Console.WriteLine(new IntPtr(ptr)); // prints 4
ptr++;
Console.WriteLine(new IntPtr(ptr)); // prints 8
इसी तरह, टाइप long
( System.Int64
लिए उपनाम)। System.Int64
) का आकार (है। यदि एक long
पते ० में संग्रहीत किया जा सकता है, तो बाद के long
पते subsequent में संग्रहीत किया जा सकता है, और इसी तरह। कोड में:
var ptr = (long*)IntPtr.Zero;
Console.WriteLine(new IntPtr(ptr)); // prints 0
ptr++;
Console.WriteLine(new IntPtr(ptr)); // prints 8
ptr++;
Console.WriteLine(new IntPtr(ptr)); // prints 16
प्रकार void
विशेष है और void
संकेत भी विशेष हैं और उनका उपयोग कैच-ऑल पॉइंटर्स के रूप में किया जाता है जब प्रकार ज्ञात नहीं होता है या कोई फर्क नहीं पड़ता है। उनके आकार-अज्ञेय प्रकृति के कारण, void
बिंदुओं को बढ़ाया या घटाया नहीं जा सकता है:
var ptr = (void*)IntPtr.Zero;
Console.WriteLine(new IntPtr(ptr));
ptr++; // compile-time error
Console.WriteLine(new IntPtr(ptr));
ptr++; // compile-time error
Console.WriteLine(new IntPtr(ptr));
तारांकन प्रकार का हिस्सा है
C और C ++ में, सूचक चर की घोषणा में तारांकन अभिव्यक्ति घोषित किए जाने का हिस्सा है । सी # में, घोषणा में तारांकन प्रकार का हिस्सा है ।
C, C ++ और C # में, निम्नलिखित स्निपेट एक int
पॉइंटर घोषित करता है:
int* a;
C और C ++ में, निम्नलिखित स्निपेट एक int
पॉइंटर और एक int
चर घोषित करता है। C # में, यह दो int
बिंदुओं की घोषणा करता है:
int* a, b;
सी और सी ++ में निम्नलिखित स्निपेट दो वाणी int
संकेत दिए गए। C # में, यह अमान्य है:
int *a, *b;
शून्य *
C # C और C ++ से एक प्रकार-अज्ञेय और आकार-अज्ञेय सूचक के रूप में void*
का उपयोग करता है।
void* ptr;
किसी भी पॉइंटर प्रकार को एक निहित रूपांतरण का उपयोग करके void*
किया जा सकता है:
int* p1 = (int*)IntPtr.Zero;
void* ptr = p1;
रिवर्स को एक स्पष्ट रूपांतरण की आवश्यकता होती है:
int* p1 = (int*)IntPtr.Zero;
void* ptr = p1;
int* p2 = (int*)ptr;
सदस्य का उपयोग कर ->
C # को C और C ++ से प्रतीक का उपयोग प्राप्त होता है ->
एक टाइप पॉइंटर के माध्यम से उदाहरण के सदस्यों तक पहुंचने के साधन के रूप में।
निम्नलिखित संरचना पर विचार करें:
struct Vector2
{
public int X;
public int Y;
}
यह अपने सदस्यों तक पहुँचने के लिए ->
के उपयोग का एक उदाहरण है:
Vector2 v;
v.X = 5;
v.Y = 10;
Vector2* ptr = &v;
int x = ptr->X;
int y = ptr->Y;
string s = ptr->ToString();
Console.WriteLine(x); // prints 5
Console.WriteLine(y); // prints 10
Console.WriteLine(s); // prints Vector2
जेनेरिक पॉइंटर्स
बिंदुओं का समर्थन करने के लिए एक प्रकार का मानदंड संतुष्ट होना चाहिए (देखें रिमार्क्स ) सामान्य बाधाओं के संदर्भ में व्यक्त नहीं किया जा सकता है। इसलिए, जेनेरिक प्रकार पैरामीटर के माध्यम से प्रदान किए गए प्रकार को सूचक घोषित करने का कोई भी प्रयास विफल हो जाएगा।
void P<T>(T obj)
where T : struct
{
T* ptr = &obj; // compile-time error
}