Unsafe code in c#-: The core C# language differs notably from C and C++ in its omission of pointers as a data type. In C# provides references and the ability to create objects that are managed by a garbage collector. This design, coupled with other features, makes C# a much safer language than C or C++.
In the core C# language, it is simply not possible to have an uninitialized variable, a “dangling” pointer, or an expression that indexes an array beyond its bounds. These constraints eliminate whole categories of bugs that routinely plague C and C++ programs.
Every pointer type construct in C or C++ has a reference type counterpart in C#, nonetheless, there are situations where access to pointer types becomes a necessity. For example, interfacing with the underlying operating system, accessing a memory-mapped device, or implementing a time-critical algorithm may not be possible or practical without access to pointers. To address this need, C# provides the ability to write unsafe code.
In unsafe code is possible to declare and operate on pointers, to perform conversions between pointers and integral types, to take the addresses of variables, and so forth. In a sense, writing unsafe code is much like writing C code within a C# program.
Unsafe code is, in fact, a “safe” feature from the perspective of both developers and users. It must be clearly marked with the modifier unsafe, so developers can’t possibly use unsafe features accidentally, and the execution engine works to ensure that unsafe code cannot be executed in an untrusted environment.
Unsafe context-: The unsafe features of C# are available only in unsafe contexts. An unsafe context is introduced by including an unsafe modifier in the declaration of a type or member, or by employing an unsafe-statement as like…
- A declaration of a class, struct, interface, or delegate may include an unsafe modifier, in which case the entire textual extent of that type declaration (including the body of the class, struct, or interface) is considered an unsafe context.
- A declaration of a field, method, property, event, indexer, operator, instance constructor, destructor, or static constructor may include an unsafe modifier, in which case the entire textual extent of that member declaration is considered an unsafe context.
- An unsafe-statement enables the use of an unsafe context within a block. The entire textual extent of the associated block is considered an unsafe context.
for example
public struct Node { public int Value; public unsafe Node* Left; public unsafe Node* Right; }
Pointer -: A pointer is a variable whose value is the address of another variable as like the direct address of the memory location. similar to any variable or constant, we must declare a pointer before we can use it to store any variable address.
Pointer Types -:In an unsafe context, a type may be a pointer-type as well as a value-type or a reference-type. A pointer-type may also be used in a type of expression outside of an unsafe context, as such usage is not unsafe
Some pointer list has been given here
Pointer conversion -: In unsafe context the set of available implicit conversions is extended to include the following implicit pointer conversions as like…
- From any pointer-type to the type void*
- From the null literal to any pointer-type
in an unsafe context, the set of available explicit conversions is extended to include the following explicit pointer conversions as like
- From any pointer-type to any other pointer-type
- From sbyte, byte, short, ushort, int, uint, long, or ulong to any pointer-type
- From any pointer-type to sbyte, byte, short, ushort, int, uint, long, or ulong
Finally, in an unsafe context, the set of standard implicit conversions includes the following pointer conversion as like
- From any pointer-type to the type void*
Conversions between two pointer types never change the actual pointer value. In other words, a conversion from one pointer type to another has no effect on the underlying address given by the pointer.
Pointer arrays -: In an unsafe context, arrays of pointers can be constructed. Only some of the conversions that apply to other array types are allowed on pointer arrays.
Pointer using retrieve data value-: we can retrieve the data stored at the located referenced by the pointer variable, using the ToString() method. The following example like …
using System; namespace UnsafeCodeApplication { class Program { public static void Main() { unsafe { int var = 50; int* p = &var; Console.WriteLine("Data is: {0} " , var); Console.WriteLine("Data is: {0} " , p->ToString()); Console.WriteLine("Address is: {0} " , (int)p); } Console.ReadKey(); } } }
Access of array elements using Pointer-: In C# programming language an array name and a pointer to a data type are not same variable type. For example, int *p and int[] p, are not same type. we can increment the pointer variable p because it is not fixed in memory but an array address is fixed in memory, and we can’t increment that.
So if we need to access an array data using a pointer variable, as we traditionally do in C, or C++ we need to fix the pointer using the fixed keyword. Like this example
using System; namespace UnsafeCodeApplication { class TestPointer { public unsafe static void Main() { int[] list = {10, 20, 30}; fixed(int *ptr = list) /* let us have array address in pointer */ for ( int i = 0; i < 3; i++) { Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i)); Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i)); } Console.ReadKey(); } } }