You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/csharp/language-reference/unsafe-code.md
+50-26Lines changed: 50 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
-
title: "Unsafe code, pointers to data, and function pointers"
2
+
title: "Unsafe code"
3
3
description: Learn about unsafe code, pointers, and function pointers. C# requires you to declare an unsafe context to use these features to directly manipulate memory or function pointers (unmanaged delegates).
4
-
ms.date: 02/06/2025
4
+
ms.date: 07/07/2025
5
5
f1_keywords:
6
6
- "functionPointer_CSharpKeyword"
7
7
helpviewer_keywords:
@@ -13,41 +13,66 @@ helpviewer_keywords:
13
13
- "C# language, pointers"
14
14
- "pointers [C#], about pointers"
15
15
---
16
-
# Unsafe code, pointer types, and function pointers
17
16
18
-
Most of the C# code you write is "verifiably safe code." *Verifiably safe code* means .NET tools can verify that the code is safe. In general, safe code doesn't directly access memory using pointers. It also doesn't allocate raw memory. It creates managed objects instead.
17
+
# Unsafe code
19
18
20
-
C# supports an [`unsafe`](keywords/unsafe.md) context, in which you can write *unverifiable*code. In an `unsafe` context, code can use pointers, allocate and free blocks of memory, and call methods using function pointers. Unsafe code in C# isn't necessarily dangerous; it's just code whose safety can't be verified.
19
+
Unsafe code is a dialect of C# that unlocks powerful capabilities often needed for interoperability with native libraries, high-performance algorithms, and other low-level programming needs. However, these capabilities bypass C#'s usual safety checks, placing the responsibility for correctness squarely on the unsafe code author. Mistakes in unsafecode can lead to bugs like buffer overruns and use-after-free errors. To help isolate risks, unsafe code must appear within an [`unsafe`](keywords/unsafe.md) context, keeping it clearly separated from regular safe code and making it easier to audit.
21
20
22
-
Unsafe code has the following properties:
21
+
In contrast, most C# code is safe code. Safe code always accesses, uses, and releases memory in ways that are proven correct by the C# compiler and .NET runtime.
23
22
24
-
- Methods, types, and code blocks can be defined as unsafe.
25
-
- In some cases, unsafe code can increase an application's performance by removing array bounds checks.
26
-
- Unsafe code is required when you call native functions that require pointers.
23
+
Within an `unsafe` context, you can use pointers, manually allocate and free blocks of memory, and call methods through function pointers.
24
+
25
+
Unsafe code has the following characteristics:
26
+
27
+
- Methods, types, and code blocks can be marked as unsafe.
28
+
- Removing array bounds checks in unsafe code can, in some cases, improve performance.
29
+
- Unsafe code is required for calling native functions that use pointers.
27
30
- Using unsafe code introduces security and stability risks.
28
-
-The code that contains unsafe blocks must be compiled with the [**AllowUnsafeBlocks**](compiler-options/language.md#allowunsafeblocks) compiler option.
31
+
-Code containing unsafe blocks must be compiled with the [`AllowUnsafeBlocks`](compiler-options/language.md#allowunsafeblocks) compiler option.
29
32
30
33
## Pointer types
31
34
32
-
In an unsafe context, a type can be a pointer type, in addition to a value type, or a reference type. A pointer type declaration takes one of the following forms:
35
+
In an unsafe context, a type can be a pointer type, in addition to a value type, or a reference type. A pointer type declaration takes the following forms (with the `*` being the key syntax difference):
33
36
34
37
```csharp
35
38
type*identifier;
36
-
void*identifier; //allowed but not recommended
37
39
```
38
40
39
-
The type specified before the `*` in a pointer type is called the **referent type**.
40
-
41
-
Pointer types don't inherit from [object](builtin-types/reference-types.md) and no conversions exist between pointer types and `object`. Also, boxing and unboxing don't support pointers. However, you can convert between different pointer types and between pointer types and integral types.
41
+
The pointer indirection operator `*` can be used to access the contents at the location pointed to by the pointer variable. For example, consider the following declaration:
42
42
43
-
When you declare multiple pointers in the same declaration, you write the asterisk (`*`) together with the underlying type only. It isn't used as a prefix to each pointer name. For example:
43
+
The following example demonstrates a complete example of using pointer types.
44
44
45
45
```csharp
46
-
int*p1, p2, p3; // Ok
47
-
int*p1, *p2, *p3; // Invalid in C#
46
+
intnumber=42;
47
+
intnumberAgain=0;
48
+
boolsame=false;
49
+
50
+
unsafe
51
+
{
52
+
int*pointer=&number; // Assigns the address of number
53
+
numberAgain=*pointer; // Retrieves the value at that address (42)
/* Example output (pointer address will vary each run):
61
+
Pointer (address): 6127673188; Pointer value: 42
62
+
NumberAgain: 42; Same: True
63
+
*/
48
64
```
49
65
50
-
The garbage collector doesn't keep track of whether an object is being pointed to by any pointer types. If the referrant is an object in the managed heap (including local variables captured by lambda expressions or anonymous delegates), the object must be [pinned](./statements/fixed.md) for as long as the pointer is used.
66
+
The example also demonstrates how safe and unsafe code can interact. The first call to `Console.WriteLine` must be within the unsafe block because `pointer` can only be used in the `unsafe` context given its `int*` definition.
67
+
68
+
### Defining pointer types
69
+
70
+
When you declare multiple pointers in the same declaration, you write the asterisk (`*`) together with the underlying type only. For example:
71
+
72
+
```csharp
73
+
int*p1, p2, p3; // Ok
74
+
int*p1, *p2, *p3; // Invalid
75
+
```
51
76
52
77
The value of the pointer variable of type `MyType*` is the address of a variable of type `MyType`. The following are examples of pointer type declarations:
53
78
@@ -57,18 +82,17 @@ The value of the pointer variable of type `MyType*` is the address of a variable
57
82
-`char* p`: `p` is a pointer to a char.
58
83
-`void* p`: `p` is a pointer to an unknown type.
59
84
60
-
The pointer indirection operator `*` can be used to access the contents at the location pointed to by the pointer variable. For example, consider the following declaration:
61
-
62
-
```csharp
63
-
int*myVariable;
64
-
```
65
-
66
-
The expression `*myVariable` denotes the `int` variable found at the address contained in `myVariable`.
67
85
68
86
There are several examples of pointers in the articles on the [`fixed` statement](statements/fixed.md). The following example uses the `unsafe` keyword and the `fixed` statement, and shows how to increment an interior pointer. You can paste this code into the Main function of a console application to run it. These examples must be compiled with the [**AllowUnsafeBlocks**](compiler-options/language.md#allowunsafeblocks) compiler option set.
Pointer types don't inherit from [object](builtin-types/reference-types.md) and no conversions exist between pointer types and `object`. Also, boxing and unboxing don't support pointers. However, you can convert between different pointer types and between pointer types and integral types.
93
+
94
+
The garbage collector doesn't keep track of whether an object is being pointed to by any pointer types. If the referrant is an object in the managed heap (including local variables captured by lambda expressions or anonymous delegates), the object must be [pinned](./statements/fixed.md) for as long as the pointer is used.
95
+
72
96
You can't apply the indirection operator to a pointer of type `void*`. However, you can use a cast to convert a void pointer to any other pointer type, and vice versa.
73
97
74
98
A pointer can be `null`. Applying the indirection operator to a null pointer causes an implementation-defined behavior.
0 commit comments