|
| 1 | +using System; |
| 2 | + |
| 3 | +namespace operators |
| 4 | +{ |
| 5 | + public static class PointerOperators |
| 6 | + { |
| 7 | + public static void Examples() |
| 8 | + { |
| 9 | + AddressOf(); |
| 10 | + PointerIndirection(); |
| 11 | + PointerMemberAccessExample.Main(); |
| 12 | + PointerElementAccess(); |
| 13 | + PointerAddition(); |
| 14 | + PointerSubtraction(); |
| 15 | + Increment(); |
| 16 | + } |
| 17 | + |
| 18 | + private static void AddressOf() |
| 19 | + { |
| 20 | + // <SnippetAddressOf> |
| 21 | + unsafe |
| 22 | + { |
| 23 | + int number = 27; |
| 24 | + int* pointerToNumber = &number; |
| 25 | + |
| 26 | + Console.WriteLine($"Value of the variable: {number}"); |
| 27 | + Console.WriteLine($"Address of the variable: {(long)pointerToNumber:X}"); |
| 28 | + } |
| 29 | + // Output is similar to: |
| 30 | + // Value of the variable: 27 |
| 31 | + // Address of the variable: 6C1457DBD4 |
| 32 | + // </SnippetAddressOf> |
| 33 | + } |
| 34 | + |
| 35 | + private static void AddressOfFixed() |
| 36 | + { |
| 37 | + // <SnippetAddressOfFixed> |
| 38 | + unsafe |
| 39 | + { |
| 40 | + byte[] bytes = { 1, 2, 3 }; |
| 41 | + fixed (byte* pointerToFirst = &bytes[0]) |
| 42 | + { |
| 43 | + // The address stored in pointerToFirst |
| 44 | + // is valid only inside this fixed statement block. |
| 45 | + } |
| 46 | + } |
| 47 | + // </SnippetAddressOfFixed> |
| 48 | + } |
| 49 | + |
| 50 | + private static void PointerIndirection() |
| 51 | + { |
| 52 | + // <SnippetPointerIndirection> |
| 53 | + unsafe |
| 54 | + { |
| 55 | + char letter = 'A'; |
| 56 | + char* pointerToLetter = &letter; |
| 57 | + Console.WriteLine($"Value of the `letter` variable: {letter}"); |
| 58 | + Console.WriteLine($"Address of the `letter` variable: {(long)pointerToLetter:X}"); |
| 59 | + |
| 60 | + *pointerToLetter = 'Z'; |
| 61 | + Console.WriteLine($"Value of the `letter` variable after update: {letter}"); |
| 62 | + } |
| 63 | + // Output is similar to: |
| 64 | + // Value of the `letter` variable: A |
| 65 | + // Address of the `letter` variable: DCB977DDF4 |
| 66 | + // Value of the `letter` variable after update: Z |
| 67 | + // </SnippetPointerIndirection> |
| 68 | + } |
| 69 | + |
| 70 | + // <SnippetMemberAccess> |
| 71 | + public struct Coords |
| 72 | + { |
| 73 | + public int X; |
| 74 | + public int Y; |
| 75 | + public override string ToString() => $"({X}, {Y})"; |
| 76 | + } |
| 77 | + |
| 78 | + public class PointerMemberAccessExample |
| 79 | + { |
| 80 | + public static unsafe void Main() |
| 81 | + { |
| 82 | + Coords coords; |
| 83 | + Coords* p = &coords; |
| 84 | + p->X = 3; |
| 85 | + p->Y = 4; |
| 86 | + Console.WriteLine(p->ToString()); // output: (3, 4) |
| 87 | + } |
| 88 | + } |
| 89 | + // </SnippetMemberAccess> |
| 90 | + |
| 91 | + private static void PointerElementAccess() |
| 92 | + { |
| 93 | + // <SnippetElementAccess> |
| 94 | + unsafe |
| 95 | + { |
| 96 | + char* pointerToChars = stackalloc char[123]; |
| 97 | + |
| 98 | + for (int i = 65; i < 123; i++) |
| 99 | + { |
| 100 | + pointerToChars[i] = (char)i; |
| 101 | + } |
| 102 | + |
| 103 | + Console.Write("Uppercase letters: "); |
| 104 | + for (int i = 65; i < 91; i++) |
| 105 | + { |
| 106 | + Console.Write(pointerToChars[i]); |
| 107 | + } |
| 108 | + } |
| 109 | + // Output: |
| 110 | + // Uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| 111 | + // </SnippetElementAccess> |
| 112 | + Console.WriteLine(); |
| 113 | + } |
| 114 | + |
| 115 | + private static void PointerAddition() |
| 116 | + { |
| 117 | + // <SnippetAddNumber> |
| 118 | + unsafe |
| 119 | + { |
| 120 | + const int Count = 3; |
| 121 | + int[] numbers = new int[Count] { 10, 20, 30 }; |
| 122 | + fixed (int* pointerToFirst = &numbers[0]) |
| 123 | + { |
| 124 | + int* pointerToLast = pointerToFirst + (Count - 1); |
| 125 | + |
| 126 | + Console.WriteLine($"Value {*pointerToFirst} at address {(long)pointerToFirst}"); |
| 127 | + Console.WriteLine($"Value {*pointerToLast} at address {(long)pointerToLast}"); |
| 128 | + } |
| 129 | + } |
| 130 | + // Output is similar to: |
| 131 | + // Value 10 at address 1818345918136 |
| 132 | + // Value 30 at address 1818345918144 |
| 133 | + // </SnippetAddNumber> |
| 134 | + } |
| 135 | + |
| 136 | + private static void PointerSubtraction() |
| 137 | + { |
| 138 | + // <SnippetSubtractPointers> |
| 139 | + unsafe |
| 140 | + { |
| 141 | + int* numbers = stackalloc int[] { 0, 1, 2, 3, 4, 5 }; |
| 142 | + int* p1 = &numbers[1]; |
| 143 | + int* p2 = &numbers[5]; |
| 144 | + Console.WriteLine(p2 - p1); // output: 4 |
| 145 | + } |
| 146 | + // </SnippetSubtractPointers> |
| 147 | + } |
| 148 | + |
| 149 | + private static void Increment() |
| 150 | + { |
| 151 | + // <SnippetIncrement> |
| 152 | + unsafe |
| 153 | + { |
| 154 | + int* numbers = stackalloc int[] { 0, 1, 2 }; |
| 155 | + int* p1 = &numbers[0]; |
| 156 | + int* p2 = p1; |
| 157 | + Console.WriteLine($"Before operation: p1 - {(long)p1}, p2 - {(long)p2}"); |
| 158 | + Console.WriteLine($"Postfix increment of p1: {(long)(p1++)}"); |
| 159 | + Console.WriteLine($"Prefix increment of p2: {(long)(++p2)}"); |
| 160 | + Console.WriteLine($"After operation: p1 - {(long)p1}, p2 - {(long)p2}"); |
| 161 | + } |
| 162 | + // Output is similar to |
| 163 | + // Before operation: p1 - 816489946512, p2 - 816489946512 |
| 164 | + // Postfix increment of p1: 816489946512 |
| 165 | + // Prefix increment of p2: 816489946516 |
| 166 | + // After operation: p1 - 816489946516, p2 - 816489946516 |
| 167 | + // </SnippetIncrement> |
| 168 | + } |
| 169 | + } |
| 170 | +} |
0 commit comments