1. using System;
2. using System.Collections.Generic;
3. using System.Text;
4. namespace UnsafeCode
5. {
6. #region Unsafe types and members (just for testing purposes)
7. // This entire structure is 'unsafe' and can
8. // be used only in an unsafe context.
9. public unsafe struct Node
10. {
11. public int Value;
12. public Node* Left;
13. public Node* Right;
14. }
15. // This struct is safe, but the Node* members
16. // are not. Technically, you may access 'Value' from
17. // outside an unsafe context, but not 'Left' and 'Right'.
18. public struct Node2
19. {
20. public int Value;
21. // These can be accessed only in an unsafe context!
22. public unsafe Node2* Left;
23. public unsafe Node2* Right;
24. }
25. #endregion
26. #region Simple Point / PointRef
27. struct Point
28. {
29. public int x;
30. public int y;
31. public override string ToString()
32. { return string.Format("({0}, {1})", x, y); }
33. }
34. class PointRef
35. {
36. public int x;
37. public int y;
38. public override string ToString()
39. { return string.Format("({0}, {1})", x, y); }
40. }
41. #endregion
42. class Program
43. {
44. static void Main(string[] args)
45. {
46. Console.WriteLine("***** Fun with Pointers *****");
47. #region Swap 2 ints safely and unsafely
48. // Values for swap.
49. int i = 10, j = 20;
50. // Swap values 'safely'.
51. Console.WriteLine("\n***** Safe swap *****");
52. Console.WriteLine("Values before safe swap: i = {0}, j = {1}", i, j);
53. SafeSwap(ref i, ref j);
54. Console.WriteLine("Values after safe swap: i = {0}, j = {1}", i, j);
55. // Swap values 'unsafely'.
56. Console.WriteLine("\n***** Unsafe swap *****");
57. Console.WriteLine("Values before unsafe swap: i = {0}, j = {1}", i, j);
58. unsafe { UnsafeSwap(&i, &j); }
59. Console.WriteLine("Values after unsafe swap: i = {0}, j = {1}", i, j);
60. Console.WriteLine();
61. #endregion
62. UsePointerToPoint();
63. Console.WriteLine();
64. UseSizeOfOperator();
65. Console.ReadLine();
66. }
67. public static void SafeSwap(ref int i, ref int j)
68. {
69. int temp = i;
70. i = j;
71. j = temp;
72. }
73. #region Various unsafe methods
74. unsafe static void PrintValueAndAddress()
75. {
76. int myInt;
77. // Define an int pointer, and
78. // assign it the address of myInt.
79. int* ptrToMyInt = &myInt;
80. // Assign value of myInt using pointer indirection.
81. *ptrToMyInt = 123;
82. // Print some stats.
83. Console.WriteLine("Value of myInt {0}", myInt);
84. Console.WriteLine("Address of myInt {0:X}", (int)&ptrToMyInt);
85. }
86. unsafe static void SquareIntPointer(int* myIntPointer)
87. {
88. // Work with pointer types here!
89. // Square the value just for a test.
90. *myIntPointer *= *myIntPointer;
91. }
92. unsafe public static void UnsafeSwap(int* i, int* j)
93. {
94. int temp = *i;
95. *i = *j;
96. *j = temp;
97. }
98. unsafe static void UsePointerToPoint()
99. {
100. // Access members via pointer.
101. Point point;
102. Point* p = &point;
103. p->x = 100;
104. p->y = 200;
105. Console.WriteLine(p->ToString());
106. // Access members via pointer indirection.
107. Point point2;
108. Point* p2 = &point2;
109. (*p2).x = 100;
110. (*p2).y = 200;
111. Console.WriteLine((*p2).ToString());
112. }
113. unsafe static void UnsafeStackAlloc()
114. {
115. char* p = stackalloc char[256];
116. for (int k = 0; k < 256; k++)
117. p[k] = (char)k;
118. }
119. unsafe public static void UseAndPinPoint()
120. {
121. PointRef pt = new PointRef();
122. pt.x = 5;
123. pt.y = 6;
124. // pin pt in place so it will not
125. // be moved or GC-ed.
126. fixed (int* p = &pt.x)
127. {
128. // Use int* variable here!
129. }
130. // pt is now unpinned, and ready to be GC-ed.
131. Console.WriteLine("Point is: {0}", pt);
132. }
133. unsafe static void UseSizeOfOperator()
134. {
135. Console.WriteLine("The size of short is {0}.", sizeof(short));
136. Console.WriteLine("The size of int is {0}.", sizeof(int));
137. Console.WriteLine("The size of long is {0}.", sizeof(long));
138. Console.WriteLine("The size of Point is {0}.", sizeof(Point));
139. }
140. #endregion
141. }
142. }