Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Apr 13, 2024
1 parent 8aaaf9c commit df1a046
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 12 deletions.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ struct C
public const int con = 0;
unsafe void M(int j, K k)
{
fixed (int* p = &j) { } // CS0213
fixed (int* p = &j) { } // CS0213 // [!code error]
fixed (int* p = &k.k) { }
int local = 0;
fixed (int* p = &local) { } // CS0213
fixed (int* p = &local) { } // CS0213 // [!code error]
int[] localArray = [];
fixed (int* p = localArray) fixed (int* pp = p) { } // CS8385
fixed (int* p = localArray) fixed (int* pp = p) { } // CS8385 // [!code error]
string localString = "abc";
fixed (char* p = localString) fixed (char* pp = p) { } // CS8385
fixed (char* p = localString) fixed (char* pp = p) { } // CS8385 // [!code error]
K kk = new();
fixed (int* p = &kk.k) { }
fixed (int* p = &this.instanceMember) { }
fixed (int* p = &C.shared) { }
fixed (int* p = &C.con) { } // CS0211
fixed (int* p = &C.con) { } // CS0211 // [!code error]
}
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,30 @@ Fixed-size buffers are used to declare “C-style” in-line arrays as members o

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

- **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

struct C
{
public static unsafe fixed byte Buffer[30]; // [!code error]
public unsafe void M()
{
C c = new();
_ = c.Buffer[0]; // compiles
}
}
```

- Element type must be one of the following: `bool`, `byte`, `short`, `int`, `long`, `char`, `sbyte`, `ushort`, `uint`, `ulong`, `float` or `double`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

## 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.
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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Pointer Array

```cs
int** p = stackalloc int*[30];
int*** pp = stackalloc int**[10];
unsafe
{
int* p = stackalloc int[10];
int** pp = stackalloc int*[10];
int*** ppp = stackalloc int**[10];
int**** pppp = stackalloc int***[10];
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Function Pointer

> Function pointer can only be created by referencing a static method.
:::info Reference
See: [Function pointers](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code#function-pointers)
:::

## Declaration

```cs
delegate*<void> f = &M;
delegate*<int, void> g = &N;
static void M() { }
static void N(int a) { }
```

## Invocation

A function pointer is a pure reference to the function without the delegate wrapper.
There's no member of it to be accessed using `.`, can only be invoked by `()`;

```cs{3}
delegate*<void> f = &M;
delegate*<int, void> g = &N;
f(); g(default);
static void M() { }
static void N(int a) { }
```

## Type parameter variant

```cs{2,4}
delegate*<int, int, int> h = &O;
delegate*<char*, int*, int*> i = &P;
static int O(int a, int b) => default;
static unsafe int* P(void* m, int* b) => default;
```

## Operator

```cs

```

## Calling Conventions

### `managed`

- `managed` is the default calling convention of a function pointer.

```cs
delegate*<void> f = &M;
delegate* managed<void> g = &M;
static void M() { }
```

### `unmanaged`

- `Cdecl`

- `Stdcall`

- `Fastcall`

- `Thiscall`

- Default `unmanaged` calling convention

The default `unmanaged` calling convention is left to CLR to make the decision.

```cs
public unsafe static void M<T>(delegate* unmanaged<T> f) { }
```

## Type Checking

Type checking of two function pointer includes function signatures and their calling convention.

```cs
delegate*<void> f = &M;
delegate* managed<void> g = &N;
delegate* unmanaged<void> h = ...;
f = g;
g = h; // calling convention not matched! // [!code error]
static void M() { }
static void N() { }
```

0 comments on commit df1a046

Please sign in to comment.