Pointers are defined as a variable that contains the memory address of another variable. Pointers in C# are used whenever there is a statement that is unsafe and is marked by unsafe keyword. Those types of statements are not in control of garbage collectors and use pointer variables.
Syntax: Pointers can be declared as
type *var name; int* a;
Here * is called a de-reference operator and a is the variable that contains the address of type int.
Example
int *p = & x; // where &x is the memory address of x Console.WriteLine((int)p) // displaying memory address Console.WriteLine(*p) // displaying value at memory address
Below are the examples that show how it works in C#.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Pointers { class Demo { public void Method() { unsafe { int a = 40; int b = 20; int* ptr1 = &a; int* ptr2 = &b; Console.WriteLine(*ptr1); // displaying the value Console.WriteLine(*ptr2); // displaying the value Console.WriteLine((int)ptr1); // displaying the address Console.WriteLine((int)ptr2); // displaying the address } } } class Example { // main method public static void Main() { Demo d = new Demo(); d.Method(); } } }
There are different ways to execute statements as unsafe like a Modifier, constructor, etc. In the above example, a group of statements are marked as unsafe. In the above code, there are two variables a and b with values 40 and 20 respectively and pointers contain their addresses. Console.WriteLine() is used to display the values and addresses of the variables.
Output:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Pointers { class Demo { public unsafe void Method() { int a = 50; int b = 20; int* ptr1 = &a; int* ptr2 = &b; Console.WriteLine(*ptr1); // displaying the value Console.WriteLine(*ptr2); // displaying the value Console.WriteLine((int)ptr1); // displaying the address Console.WriteLine((int)ptr2); // displaying the address } } class Example { // main method public static void Main() { Demo d = new Demo(); d.Method(); } } }
In the above example, unsafe is used with the method which has two variables a and b with values 50 and 20 respectively. Pointers *ptr1 and *ptr2 points to their memory addresses.
Output:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Pointers { class Demo { public unsafe static void Main() { int[] array = { 10, 20, 30, 40, 50 }; // declaring array fixed (int* ptr = array) // fixed for pinning the object /* let us have array address in pointer */ for (int i = 0; i < 5; i++) { Console.WriteLine("Value of array[{0}]={1}", i, *(ptr + i)); Console.WriteLine("Address of array[{0}]={1}", i, (int)(ptr + i)); Console.ReadKey(); } } } }
In the above code, an array is defined which consists of five elements and Console.WriteLine () is used to display the value of array elements and the address of the array elements. There is a concept in C# which is known as the Pinning of an object. In the above code, a fixed statement is used for object pinning so that the garbage collector will not let the object to move and “pin” it. It may affect the runtime efficiency.
Output:
using System; namespace Pointers { // Struct employee struct Employee { // members // employee id and salary public int empid; public double salary; // Constructor to initialize values public Employee(int e, double s) { empid = e; salary = s; } }; // end of struct class Program { // Main Method static void Main(string[] args) { // unsafe so as to use pointers unsafe { // Declaring two employee Variables Employee E1 = new Employee(798, 30000); Employee E2 = new Employee(799, 31000); // Declaring two employee pointers // and initializing them with addresses // of E1 and E2 Employee* E1_ptr = &E1; Employee* E2_ptr = &E2; // Displaying details of employees using pointers // Using the arrow ( -> ) operator Console.WriteLine("Details of Employee 1"); Console.WriteLine("Employee Id: {0} Salary: {1}", E1_ptr->empid, E1_ptr->salary); Console.WriteLine("Details of Employee 2"); Console.WriteLine("Employee Id: {0} Salary: {1}", E2_ptr->empid, E2_ptr->salary); } // end unsafe } // end main } // end class }
In the above example, employee struct with members employee id and salary and parameterize constructor to initialize the values. Pointers point to structs which contain primitive value type instead of structs containing reference type. In main method, there are two employee variables and employee pointers which are initialized with addresses E1 and E2. Console.WriteLine() is used to display the details of the employee using pointers.
Output:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Pointers { class Demo { public static void Main() { unsafe { int* arr = stackalloc int[6]; // declaring array arr[0] = 10; arr[1] = 20; arr[2] = 30; arr[3] = 40; arr[4] = 50; arr[5] = 60; for (int i = 0; i < 6; i++) { Console.WriteLine($"Value at {i}: {arr[i]}"); Console.ReadKey(); } } } } }
In the above code, the stackalloc keyword is used, in which memory is allocated on the stack. The memory executed on the block of stack is created during the method execution. stackalloc is better in performance and there is no need to pin the array. It is better than the heap-allocated array as there is no need to free it because it automatically freed when the method returns.
Output:
In pointers, conversions are of an implicit and explicit type. An implicit type of conversion is like any pointer type to void* type and null to any pointer type. In explicit type, conversions are from byte, sbyte, ushort, short, uint, int, ulong, long to any pointer type or vice versa and one pointer to another pointer.
So pointers are used to point the memory addresses and execute them with an unsafe code of statements. It only used in an unmanaged environment and is not tracked by the garbage collector. Pointers are used in a stack, queue, etc.
The above is the detailed content of Pointers in C#. For more information, please follow other related articles on the PHP Chinese website!