Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

Chapter 140: Pointers

Section 140.1: Pointers for array access

This example demonstrates how pointers can be used for C-like access to C# arrays.

unsafe

{

var buffer = new int[1024]; fixed (int* p = &buffer[0])

{

for (var i = 0; i < buffer.Length; i++)

{

*(p + i) = i;

}

}

}

The unsafe keyword is required because pointer access will not emit any bounds checks that are normally emitted when accessing C# arrays the regular way.

The fixed keyword tells the C# compiler to emit instructions to pin the object in an exception-safe way. Pinning is required to ensure that the garbage collector will not move the array in memory, as that would invalidate any pointers pointing within the array.

Section 140.2: Pointer arithmetic

Addition and subtraction in pointers works di erently from integers. When a pointer is incremented or decremented, the address it points to is increased or decreased by the size of the referent type.

For example, the type int (alias for System.Int32) has a size of 4. If an int can be stored in address 0, the subsequent int can be stored in address 4, and so on. In code:

var ptr = (int*)IntPtr.Zero; Console.WriteLine(new IntPtr(ptr)); // prints 0 ptr++;

Console.WriteLine(new IntPtr(ptr)); // prints 4 ptr++;

Console.WriteLine(new IntPtr(ptr)); // prints 8

Similarly, the type long (alias for System.Int64) has a size of 8. If a long can be stored in address 0, the subsequent longcan be stored in address 8, and so on. In code:

var ptr = (long*)IntPtr.Zero; Console.WriteLine(new IntPtr(ptr)); // prints 0 ptr++;

Console.WriteLine(new IntPtr(ptr)); // prints 8 ptr++;

Console.WriteLine(new IntPtr(ptr)); // prints 16

The type void is special and void pointers are also special and they are used as catch-all pointers when the type isn't known or doesn't matter. Due to their size-agnostic nature, void pointers cannot be incremented or decremented:

var ptr = (void*)IntPtr.Zero;

GoalKicker.com – C# Notes for Professionals

686

Console.WriteLine(new IntPtr(ptr)); ptr++; // compile-time error

Console.WriteLine(new IntPtr(ptr)); ptr++; // compile-time error

Console.WriteLine(new IntPtr(ptr));

Section 140.3: The asterisk is part of the type

In C and C++, the asterisk in the declaration of a pointer variable is part of the expression being declared. In C#, the asterisk in the declaration is part of the type.

In C, C++ and C#, the following snippet declares an int pointer:

int* a;

In C and C++, the following snippet declares an int pointer and an int variable. In C#, it declares two int pointers:

int* a, b;

In C and C++, the following snippet declares two int pointers. In C#, it is invalid:

int *a, *b;

Section 140.4: void*

C# inherits from C and C++ the usage of void* as a type-agnostic and size-agnostic pointer.

void* ptr;

Any pointer type can be assigned to void* using an implicit conversion:

int* p1 = (int*)IntPtr.Zero; void* ptr = p1;

The reverse requires an explicit conversion:

int* p1 = (int*)IntPtr.Zero; void* ptr = p1;

int* p2 = (int*)ptr;

Section 140.5: Member access using ->

C# inherits from C and C++ the usage of the symbol -> as a means of accessing the members of an instance through a typed pointer.

Consider the following struct:

struct Vector2

{

public int X; public int Y;

}

This is an example of the usage of -> to access its members:

GoalKicker.com – C# Notes for Professionals

687

Vector2 v; v.X = 5; v.Y = 10;

Vector2* ptr = &v; int x = ptr->X; int y = ptr->Y;

string s = ptr->ToString();

Console.WriteLine(x); // prints 5

Console.WriteLine(y); // prints 10

Console.WriteLine(s); // prints Vector2

Section 140.6: Generic pointers

The criteria that a type must satisfy in order to support pointers (see Remarks) cannot be expressed in terms of generic constraints. Therefore, any attempt to declare a pointer to a type provided through a generic type parameter will fail.

void P<T>(T obj) where T : struct

{

T* ptr = &obj; // compile-time error

}

GoalKicker.com – C# Notes for Professionals

688