Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Microsoft C# Professional Projects - Premier Press.pdf
Скачиваний:
177
Добавлен:
24.05.2014
Размер:
14.65 Mб
Скачать

836

Part X

APPENDIXES

 

 

 

words, unmanaged code does not provide CLR with metadata. CLR is not sure of the safe execution of unmanaged code, and therefore, unmanaged code is considered to be unsafe. You can only run unsafe code in a fully trusted environment. Because of the problems that you face while working with pointers, C# allows you to use pointers in unsafe code.

After declaring a pointer in unsafe code, you need to implement pointers.

Implementing Pointers

A pointer that you declare must be of the type pointer. You can declare a pointer type by using the asterisk (*) sign after the void keyword or by declaring the pointer as an unmanaged-type. For example:

void *

or

unmanaged-type *

In the preceding syntax, void is the data type of the variable to which the pointer points. This data type is called the reference type. However, an unmanaged-type can be of any data type other than the reference type. The unmanaged-type data types

include all variable types, enum, pointer, or struct.

While working with pointer types, you need to remember the following guidelines:

The void type pointer points to any variable type that is not known to the user. Therefore, you cannot use the indirection operator with the void type pointer. In addition, you cannot perform any arithmetic operation on the void pointer. However, you can type cast the void pointer to any other pointer type and vice versa. You will learn about the indirection operator and pointer arithmetic later in this appendix.

Because pointers are of unmanaged-type, they are not managed by garbage

collector. Therefore, you cannot declare a pointer pointing to a reference

type.

C# does not allow a pointer to inherit from an object. In addition, you cannot type cast a pointer type to an object and vice versa. This implies that you can neither box nor unbox a pointer. However, if you convert a pointer to a value type, you can box this value type variable.

UNSAFE CODE Appendix A 837

As you have seen, pointers are used with unmanaged code. However, in some cases, C# also allows you to use pointers with managed code. The following section discusses the use of pointers with managed code in detail.

Using Pointers with Managed Code

The main problem of using pointers with managed code is that the garbage collection system of CLR controls the execution of the managed code. The garbage collection system moves the objects internally in the memor y. If you use pointers in managed code, the garbage collector does not automatically change the address stored in the pointer. This is because the garbage collector does not have control over pointers. This may cause problems with your code, as the pointer points to incorrect memory locations.

To sol ve this problem, C# allows you to prevent CLR from moving a specified object in the memory. To do this, you use the fixed statement. To understand the fixed statement, look at its syntax.

fixed (pointer declaration statement)

Here, the fixed keyword is used to pin the position of the managed object. The pointer declaration statement declares and initializes a pointer with the address of the managed object. Until the C# compiler finishes the compilation of the program code, the garbage collection system is not allowed to move the object that is marked with the fixed keyword.

Having seen the use of pointers in managed and unmanaged code, you will learn about the operators that you can use to work with pointers.

Working with Pointers

In addition to the operators used with variables, C# supports some more operators to be used with pointers.

indirection operator. The indirection operator is used to retrieve the content stored at the memory address referred by the pointer. In other words, the indirection operator converts a pointer to a variable of the value type. You can convert a pointer to almost every variable data type or a struct. However, you cannot convert a pointer to a class or an array. This operator is denoted by an asterisk (*) sign, and it is also called a

dereference operator.

838

Part X

APPENDIXES

 

 

 

address operator. The address operator is used to retrieve the address of the memory location referred by the pointer. In other words, the address operator converts the variable of the value type to a pointer. This operator is denoted by the ampersand (&) sign.

sizeof operator. The sizeof operator is used with the unmanaged-type

pointer to find out the size of the pointer. While allocating memory to

the pointer, you may need to know the size of the pointer. The return

 

 

 

Y

type of the sizeof operator is integer, and it can be used to find the

size of both default and user-defined unmanaged pointers.

 

 

F

stackalloc operator. The stackalloc operator is used to allocate mem-

 

 

M

 

ory from the call stack. The stackalloc operator has the following

syntax:

 

L

stackalloc

A

 

<data type>[expression]

 

 

E

 

Here, data type is the type of variable that you can store at the new

 

T

 

 

memory location, and expression specifies the number of memory locations to be allocated.

-> operator. he -> operator is used to access the struct members by using a pointer. You can use the -> operator as follows:

<expression> -> <identifier>

In the preceding syntax, the expression is any unmanaged-type expression, and identifier is the struct to which the pointer points.

[] operator. The [] operator is used to access an element of the pointer. The syntax of the [] operator is:

<data type>[] <identifier>

Here, the data type is the type of the pointer, and identifier specifies the name of the pointer whose elements are to be accessed.

Working with pointers also involves performing operations on pointers. The following section discusses the pointer arithmetic.

Pointer Arithmetic

Pointer arithmetic is very similar to the operations performed with variables. However, you cannot perform operations on a void type pointer. Similar to

Team-Fly®

UNSAFE CODE Appendix A 839

variables, you can use the increment (+) and the decrement (-) operators to add and subtract values from a pointer, respectively. For example, to add an integer value to a pointer, you use the following statement:

Pointer1 + 20;

Because the size of an integer is 4 bytes, the preceding statement adds 80 bytes to the pointer named Pointer1. However, to increment the value of a pointer by 1 byte, you can add a byte or an sbyte to a pointer.

Similarly, you can use the ++, --, and the comparison operators, such as <, >, ==, !=, <=, and >=, to perform operations on pointers.

In addition to performing operations on pointers, you can also type cast pointers.

Type Casting Pointers

As discussed earlier, you can type cast a pointer type to a variable type and vice versa. Pointers are used to store memory addresses, which are integer values. Therefore, it is possible to explicitly convert a pointer to an integer type. You need to convert a pointer to an integer type to display the pointer. The Console.WriteLine method does not take a pointer as a parameter. However, if you convert a pointer to an integer variable, you can pass it as a parameter to the Console.WriteLine method. To know more about pointer type casting, consider the following example:

int Integer = 20; int *Pointer1; Pointer1 = &Integer;

Console.WriteLine (“The value of Pointer1 is” + (int) Pointer1);

Here, a pointer named Pointer1 is declared and initialized with the address of an integer variable named Integer. To display the value of Pointer1, the pointer is type casted to an integer type by using the cast operator.

Because integer data type has a size of 4 bytes, you cannot use it in 64-bit systems. If you type cast a pointer to an integer value, it may result in an overflow condition. Therefore, it is advisable to type cast a pointer to a ulong type value.