Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Apr 12, 2024
1 parent af47993 commit 1a1a194
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Start your first source generator for `csharp` #
# Start your first source generator #

## Init your source generator project ##

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Releasing unsafe power

```xml
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> // [!code ++]
</PropertyGroup>

</Project>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Pointer operators

For all value and reference types, there's a pointer version of it(`T*`), **the pointer instance stores the address of the variable**.

|operator|name|usage|
|---|---|---|
|`&`|address-of operator|returns a pointer to the address of a variable|
|`*`|dereference operator|returns the variable at the address of a pointer, in other words, returns a pointer|
|`->`|pointer-to-member operator|syntactic sugar in which `x->y` is equivalent to `(*x).y`|
|`++`|pointer addition operator|adds `sizeof(T)` to the address contained in the variable|
|`--`|pointer subtraction operator|subtracts `sizeof(T)` to the address contained in the variable|
|`[]`|pointer element accessor|retrieve value of address with an offset, in which `p[i]` is equivalent to `*(p + i)`|

## Pointer Increment and Decrement

If a pointer increment or decrement operation overflows the domain of the pointer type, the result is implementation-defined, but no exceptions are produced.

```cs
T* operator ++(T* x);
T* operator --(T* x);
```

## Pointer Arithmetic

```cs
T* operator +(T* x, int y);
T* operator +(T* x, uint y);
T* operator +(T* x, long y);
T* operator +(T* x, ulong y);
T* operator +(int x, T* y);
T* operator +(uint x, T* y);
T* operator +(long x, T* y);
T* operator +(ulong x, T* y);
T* operator –(T* x, int y);
T* operator –(T* x, uint y);
T* operator –(T* x, long y);
T* operator –(T* x, ulong y);
long operator –(T* x, T* y);
```

## Pointer comparison

See [Void Pointer](./5.%20Void%20Pointer.md#Built-in%20operator)

## Operator priority

- `++` or `--` > `*`, `*p++` is equivalent to `*(p++)`.

## `sizeof` Operator
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Fixed statement

## Motivation

GC may move a managed object around during runtime, so pointing to its address is not reliable since the address possibly changes all the time. So `fixed` is to tell the GC not moving the object around.

```cs
Person person = new();
unsafe
{
// get address of a field and assign it to a new pointer
fixed (int* ptr = &person.Age)
{
// dereferencing, in which returns the variable and assign new value
*ptr = 123;
}
Console.WriteLine(person.Age);
}

class Person { public int Age; }
```

## Managed and Unmanaged

- All enums are unmanaged
- All pointers are unmanaged
- All primitive types are unmanaged.
- User defined struct containing no managed field are unmanaged

## When to use `fixed`?

```cs
class K { public int k; }
struct C
{
public int instanceMember;
public readonly static int shared;
public const int con = 0;
unsafe void M(int j, K k)
{
fixed (int* p = &j) { } // CS0213
fixed (int* p = &k.k) { }
int local = 0;
fixed (int* p = &local) { } // CS0213
int[] localArray = [];
fixed (int* p = localArray) fixed (int* pp = p) { } // CS8385
string localString = "abc";
fixed (char* p = localString) fixed (char* pp = p) { } // CS8385
K kk = new();
fixed (int* p = &kk.k) { }
fixed (int* p = &this.instanceMember) { }
fixed (int* p = &C.shared) { }
fixed (int* p = &C.con) { } // CS0211
}
}
```

1. `j` lives inside the method only, and it's unmanaged so compiler yells.
2. `k` as a reference type and managed object, can be fixed.
3. local unmanaged can't be fixed
4. local array is managed but `p` is already fixed in previous statement.
5. same as 5.
6. local managed can be fixed
7.
8. static fields are kept alive until the program ends then GC collects, so it's managed.
9. constants are simply values, not variable or field, there's no address for them.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Fixed-Size buffer

## Motivation

Fixed-size buffers are used to declare “C-style” in-line arrays as members of structs, and are primarily useful for interfacing with unmanaged APIs.

## Constraint

- Length of fixed-size buffer may only be constant.
- Fixed-size buffer may only be **declared and accessed** in unsafe context.

```cs
C c = new();
_ = c.Buffer[0]; // CS0214
struct C
{
public unsafe fixed byte Buffer[30];
public unsafe void M()
{
C c = new();
_ = c.Buffer[0];
}
}
```

- **May not be static.** But instance of its containing type can be static.
- Element type must be one of the following: `bool`, `byte`, `short`, `int`, `long`, `char`, `sbyte`, `ushort`, `uint`, `ulong`, `float` or `double`.

```cs

```
19 changes: 19 additions & 0 deletions docs/document/Unsafe CSharp/docs/Fundamentals/5. Void Pointer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Void Pointer

`void*` is the loosely typed version of any pointer(like `object` for non pointer types), the underlying type of the original pointer is mopped, so

- Cannot be deferenced.
- Arithmetic can not be performed.

## Pointer comparison

Because an implicit conversion exists from any pointer type to the void* type, operands of any pointer type can be compared using these operators. The comparison operators compare the addresses given by the two operands as if they were unsigned integers.

```cs
bool operator ==(void* x, void* y);
bool operator !=(void* x, void* y);
bool operator <(void* x, void* y);
bool operator >(void* x, void* y);
bool operator <=(void* x, void* y);
bool operator >=(void* x, void* y);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Pointer Conversion

## What does conversion do?

Conversions between two pointer types never change the actual pointer value. In other words, a conversion from one pointer type to another has no effect on the underlying address given by the pointer.

## Implicit Conversion

- Any pointer type to `void*`.
- `null` to any pointer type.

## Explicit Conversion

- `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, or `ulong` to any pointer type.
- any pointer type to any other pointer type.
- any pointer type to `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, or `ulong`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Stack Allocation

## `stackalloc` Operator

- The natural type `stackalloc` returns is the pointer of target element type(`TUnmanaged*`).
- Element type must be unmanaged type.
- Similar to `new` operator, compiler can infer the target type;

```cs
_ = stackalloc int[] { 1, 2, 3 };
_ = stackalloc[] { 1d, 2d, 3f };
_ = stackalloc byte[10];
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Pointer Array

```cs
int** p = stackalloc int*[30];
int*** pp = stackalloc int**[10];
```

0 comments on commit 1a1a194

Please sign in to comment.