7.7. Unsafe Code

The core C# language differs notably from C and C++ in its omission of pointers as a first-class data type. Instead, 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.

However, even though it is possible to model everything as references, sometimes you need pointer operations. For example, interfacing with the underlying operating system and coding certain performance-critical operations require raw pointer manipulation. Java does provide a semblance of this ability to deal with pointers through the Java Native Interface (JNI) API, which is basically a Java wrapper over C/C++ method calls. C#, on the other hand, provides the unsafe mode of operation.

In unsafe code you can declare and operate on pointers, perform conversions between pointers and integral types, take the address of variables, and so forth. In a sense, writing unsafe code is much like writing C code within a C# program.

The unsafe keyword denotes an unsafe context. You apply this keyword as a modifier in the declaration of callable members such as methods, properties, and constructors. The scope of the unsafe context extends from the parameter list to the end of the function, so pointers can also be used in the parameter list. To compile unmanaged code, you must specify the /unsafe compiler option. Unmanaged code is not verifiable by the Common Language Runtime.

Now let's look at the pointer data type.

7.7.1. The Pointer Data Type

A pointer type is written as an unmanaged type or the keyword void; this is followed by a * token. The type specified before the * in a pointer type is called the referent type of the pointer type. It represents the type of the variable to which a value of the pointer type points. A pointer is not permitted to point to a reference or to a structure that contains references, and the referent type of a pointer must be an unmanaged type. An unmanaged type is any type that isn't a reference type and doesn't contain reference type fields at any level of nesting. In other words, an unmanaged type is one of the following:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool

  • Any enum

  • Any pointer

  • Any user-defined struct that contains fields of unmanaged types only

The intuitive rule for mixing pointers and references is that referents of references (objects) are permitted to contain pointers, but referents of pointers are not permitted to contain references.

Table 7.9 shows the common pointer types.

The value of a pointer having type T* represents the address of a variable of type T. The pointer indirection operator * can be used to access this variable. For example, given a variable P of type int*, the expression *P denotes the int variable found at the address contained in P. Like an object reference, a pointer can be null. Applying the indirection operator to a null pointer results in implementation-defined behavior. A pointer with the value null is represented by all bits zero.

The void* type represents a pointer to an unknown type. Because the referent type is unknown, the indirection operator cannot be applied to a pointer of type void*, nor can any arithmetic be performed on such a pointer. However, a pointer of type void* can be cast to any other pointer type (and vice versa). Listing 7.8 shows the use of pointers in C#.

Listing 7.8. Simple Pointer Data Types (C#)
using System;
public class PointerTest {
  unsafe static void Main() {
    int i = 10;
    int* px2 = &i;
    Console.WriteLine(*px2*2);
  }
}

The output of Listing 7.8 is

20

Table 7.9. Common Pointer Types (C#)
Type (Keyword)Description
byte*Pointer to byte
char*Pointer to char
int**Pointer to pointer to int
int*[]An array of pointers to int
void*Pointer to unknown type

Because writing unsafe code is the exception rather than the norm, we will not explore details about pointer arithmetic and how pointers behave when passed as method parameters.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.22.136