unsafe C# with Example



unsafe C# with Example

The unsafe keyword can be used in type or method declarations or to declare an inline block. 
The purpose of this keyword is to enable the use of the unsafe subset of C# for the block in question. The unsafe 
subset includes features like pointers, stack allocation, C-like arrays, and so on. 
Unsafe code is not verifiable and that's why its usage is discouraged. Compilation of unsafe code requires passing a 
switch to the C# compiler. Additionally, the CLR requires that the running assembly has full trust. 
Despite these limitations, unsafe code has valid usages in making some operations more performant (e.g. array 
indexing) or easier (e.g. interop with some unmanaged libraries). 
As a very simple example 
// compile with /unsafe 
class UnsafeTest 
{ 
unsafe static void SquarePtrParam(int* p) 
{ 
*p *= *p; // the '*' dereferences the pointer. 
//Since we passed in "the address of i", this becomes "i *= i" 
} 
unsafe static void Main() 
{ 
int i = 5; 
// Unsafe method: uses address-of operator (&): 
SquarePtrParam(&i); // "&i" means "the address of i". The behavior is similar to "ref i" 
Console.WriteLine(i); // Output: 25 
} 
} 
 

While working with pointers, we can change the values of memory locations directly, rather than having to address 
them by name. Note that this often requires the use of the fixed keyword to prevent possible memory corruption 
as the garbage collector moves things around (otherwise, you may get error CS0212). Since a variable that has been 
"fixed" cannot be written to, we also often have to have a second pointer that starts out pointing to the same 
location as the first. 
void Main() 
{ 
int[] intArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
UnsafeSquareArray(intArray); 
foreach(int i in intArray) 
Console.WriteLine(i); 
} 
unsafe static void UnsafeSquareArray(int[] pArr) 
{ 
int len = pArr.Length; 
//in C or C++, we could say 
// int* a = &(pArr[0]) 
// however, C# requires you to "fix" the variable first 
fixed(int* fixedPointer = &(pArr[0])) 
{ 
//Declare a new int pointer because "fixedPointer" cannot be written to. 
// "p" points to the same address space, but we can modify it 
int* p = fixedPointer; 
for (int i = 0; i < len; i++) 
{ 
*p *= *p; //square the value, just like we did in SquarePtrParam, above 
p++; //move the pointer to the  next memory space. 
// NOTE that the pointer will move 4 bytes since "p" is an 
// int pointer and an int takes 4 bytes 
//the above 2 lines could be written as one, like this: 
// "*p *= *p++;" 
} 
} 
} 
Output: 
1 
4 
9 
16 
25 
36 
49 
64 
81 
100 
unsafe also allows the use of stackalloc which will allocate memory on the stack like _alloca in the C run-time 
library. We can modify the above example to use stackalloc as follows: 
unsafe void Main() 
{ 
 

const int len=10; 
int* seedArray = stackalloc int[len]; 
//We can no longer use the initializer "{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}" as before. 
// We have at least 2 options to populate the array. The end result of either 
// option will be the same (doing both will also be the same here). 
//FIRST OPTION: 
int* p = seedArray; // we don't want to lose where the array starts, so we 
// create a shadow copy of the pointer 
for(int i=1; i<=len; i++) 
*p++ = i; 
//end of first option 
//SECOND OPTION: 
for(int i=0; i

0 Comment's

Comment Form

Submit Comment