1. Introduction to
Pointers in C#
A pointer is
a variable that stores the memory address of another variable.
In C#, pointers are allowed only inside unsafe code, and they
work only with value types and arrays.
Pointer Declaration
Syntax
datatype* pointerName;
Example:
int* ptr;
·
Pointers
are allowed only in unsafe context.
·
C#
pointers are similar to C/C++ pointers but with more restrictions
for safety.
2. Features of
Pointers in C#
·
Pointers save memory space.
·
Execution is faster due to direct
memory access.
·
Memory access becomes more efficient.
·
A pointer cannot point to:
o A reference type
o A struct containing reference fields
·
The type before * is called the referent type.
·
Pointers can be used only inside unsafe
blocks.
Example:
unsafe{ int x = 5; int* p = &x;}
3. Unsafe Code
In C#, unsafe code
allows pointer operations.
Properties of Unsafe
Code
·
Methods,
types, and blocks can be marked with unsafe.
·
Pointer
operations allow:
o Direct memory access
o Faster execution
o Removing array bounds checks
·
Necessary
for calling native/OS-level functions.
·
Risky
because:
o CLR cannot fully check safety
o Memory corruption may occur
·
The
project must enable: AllowUnsafeBlocks
4. Enabling Unsafe
Code
In Visual Studio
Code (.csproj file):
Open .csproj and add:
<PropertyGroup> <AllowUnsafeBlocks>true</AllowUnsafeBlocks></PropertyGroup>
In Visual Studio
IDE:
Project → Properties → Build → Check
"Allow unsafe code".
ADVANTAGES OF UNSAFE CODE
·
Better performance because there are no runtime safety checks.
·
Direct memory access using pointers and fixed buffers, allowing faster raw memory
operations.
·
Useful for system-level tasks where low-level control of memory is required.
DISADVANTAGES OF UNSAFE
CODE
·
Higher security risk because the CLR cannot fully protect or check the code.
·
More chances of errors since type safety and bounds checking are bypassed.
·
Unsafe pointer access can break object access rules, leading to memory corruption
or crashes.
Exampleusing System; class MyClass{ public unsafe void Method() { int x = 10; int y = 20; int* ptr1 = &x; int* ptr2 = &y; Console.WriteLine((int)ptr1); // Memory address Console.WriteLine((int)ptr2); // Memory address Console.WriteLine(*ptr1); // Value at address Console.WriteLine(*ptr2); // Value at address }} class MyClient{ public static void Main() { MyClass mc = new MyClass(); mc.Method(); }}
CALL BY VALUE
• When you pass a variable to a method by value, C# sends only a copy of the data.
• Inside the method, any changes are applied to the copy, not the original variable.
• Therefore, the original variable remains unchanged.
How It Works Internally
Original Variable → Copy Created → Method Uses Copy → Changes Stay Inside
Example Program
using System;
class Program
{
static void ModifyValue(int x)
{
x = 20; // This only changes the COPY
}
static void Main()
{
int num = 10;
Console.WriteLine("Before ModifyValue: " + num);
ModifyValue(num); // Passing by VALUE (copy)
Console.WriteLine("After ModifyValue: " + num);
}
}
Output
Before ModifyValue: 10
After ModifyValue: 102. CALL BY REFERENCE USING ref
• ref sends the actual memory address of the variable.
• So the method can directly modify the original variable.
• Variable must be initialized before passing.
How It Works Internally
Original Variable → Address Sent → Method Changes Actual Value
Example Program
using System;
class Program
{
static void ModifyValue(ref int num)
{
num = num * 2; // This modifies the original variable
}
static void Main()
{
int number = 5; // Must be initialized
Console.WriteLine("Before: " + number);
ModifyValue(ref number); // Passing by reference
Console.WriteLine("After: " + number);
}
}
Output
Before: 5
After: 10
Explanation
• ref sends the actual memory location
• Method modifies the real value, not a copy
• So change is permanent3. CALL BY REFERENCE USING out
• out is also used to pass by reference.
• But the variable does NOT need to be initialized before passing.
• The method must assign a value before it returns.
How It Works Internally
Uninitialized Variable → Address Sent → Method Must Assign Value
Example Program
using System;
class Program
{
static void SetValue(out int num)
{
num = 10; // Must assign value
}
static void Main()
{
int number; // Uninitialized variable
SetValue(out number); // Passed by reference
Console.WriteLine("Value: " + number);
}
}
Output
Value: 10
Explanation
• Variable number was not initialized.
• out allows uninitialized variables.
• Method must set the value → num = 10.
RETRIEVING
THE DATA VALUE USING A POINTER
A
pointer is a variable that stores the memory address of
another variable.
Example:
int a = 10;int* p = &a;
·
a stores value 10
·
&a returns the memory address of a
·
p stores that address
Dereferencing
a Pointer
The * operator is used to read the value
from the memory address.
Example
Code:
using System; class Program{ unsafe static void Main() { int a = 100; int* p = &a; Console.WriteLine("Value of a: " + a); Console.WriteLine("Address of a: " + (int)p); Console.WriteLine("Value using pointer: " + *p); }}
How
it works:
|
|
Address of
variable |
|
|
Holds
address |
|
|
Reads value
from that address |
Memory
Model:
If:
a = 100address = 2001
Then:
p = 2001*p = 100
PASSING POINTER AS PARAMETER TO METHODS
Passing
a pointer as a parameter means sending the memory address of a
variable instead of its value, so the method can modify the original variable
directly.
Normal parameters pass a copy, but pointer parameters pass the address.
Syntax: unsafe void Method(int* p) and call using Method(&variable);
Example:
Swap Two Numbers Using Pointers
using System; class Program{ unsafe static void Swap(int* x, int* y) { int temp; temp = *x; *x = *y; *y = temp; } unsafe static void Main() { int a = 10; int b = 20; Console.WriteLine("Before Swap:"); Console.WriteLine("a = " + a); Console.WriteLine("b = " + b); Swap(&a, &b); Console.WriteLine("\nAfter Swap:"); Console.WriteLine("a = " + a); Console.WriteLine("b = " + b); }}
&a
passes the address, int* x receives and stores it, and *x = value
changes the original variable.
Final result: the actual values in memory are modified (e.g., swapping is
done).
Output
Memory
Before:
a = 10 b = 20
Memory
After:
a = 20 b = 10
ACCESSING ARRAY ELEMENTS USING A POINTER
In
c# int *p and int[] p, are not the same type. You can increment the pointer
variable p because it is not fixed in memory but an array address is fixed in
memory, and you can't increment that. We need to fix the pointer using
the fixed keyword to access the array elements using pointer.
Read
Array Using Pointer
using System; class Program{ unsafe static void Main() { int[] arr = { 10, 20, 30, 40, 50 }; fixed (int* ptr = arr) { for (int i = 0; i < arr.Length; i++) { Console.WriteLine(*(ptr + i)); } } }}
fixed locks the array in memory, ptr holds the first element’s address, ptr + i moves to the next element, and *(ptr + i) reads its value.
Example
2: User Input + Pointer
using System; class Program{ unsafe static void Main() { Console.Write("Enter size: "); int n = int.Parse(Console.ReadLine()); int[] arr = new int[n]; for (int i = 0; i < n; i++) { Console.Write("Enter element " + (i + 1) + ": "); arr[i] = int.Parse(Console.ReadLine()); } fixed (int* ptr = arr) { Console.WriteLine("\nAccessing using pointer:"); for (int i = 0; i < arr.Length; i++) { Console.WriteLine(*(ptr + i)); } } }}
How
it Works:
1. Takes array size
2. Accepts elements
3. Fixes memory
4. Uses pointer arithmetic
5. Dereference
6. Prints values
Comments
Post a Comment