Skip to content

Commit 973a93d

Browse files
committed
add docs for C pointers
1 parent df87044 commit 973a93d

File tree

1 file changed

+57
-3
lines changed

1 file changed

+57
-3
lines changed

doc/langref.html.in

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,7 +1694,7 @@ test "comptime @intToPtr" {
16941694
}
16951695
}
16961696
{#code_end#}
1697-
{#see_also|Optional Pointers#}
1697+
{#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
16981698
{#header_open|volatile#}
16991699
<p>Loads and stores are assumed to not have side effects. If a given load or store
17001700
should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
@@ -1823,7 +1823,9 @@ fn foo(bytes: []u8) u32 {
18231823
}
18241824
{#code_end#}
18251825
{#header_close#}
1826+
{#see_also|C Pointers#}
18261827
{#header_close#}
1828+
18271829
{#header_open|Slices#}
18281830
{#code_begin|test_safety|index out of bounds#}
18291831
const assert = @import("std").debug.assert;
@@ -3981,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {
39813983
{#code_end#}
39823984
<p>
39833985
Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,
3984-
and the transformation is guaranteed to be safe.
3986+
and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}.
39853987
</p>
39863988
{#header_open|Implicit Cast: Stricter Qualification#}
39873989
<p>
@@ -6104,6 +6106,10 @@ test "call foo" {
61046106
<p>
61056107
Converts a pointer of one type to a pointer of another type.
61066108
</p>
6109+
<p>
6110+
{#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#}
6111+
to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}.
6112+
</p>
61076113
{#header_close#}
61086114

61096115
{#header_open|@ptrToInt#}
@@ -7345,10 +7351,27 @@ fn bar(f: *Foo) void {
73457351
{#code_end#}
73467352
{#header_close#}
73477353

7348-
{#header_open|Out of Bounds Float To Integer Cast#}
7354+
{#header_open|Out of Bounds Float to Integer Cast#}
73497355
<p>TODO</p>
73507356
{#header_close#}
73517357

7358+
{#header_open|Pointer Cast Invalid Null#}
7359+
<p>At compile-time:</p>
7360+
{#code_begin|test_err|null pointer casted to type#}
7361+
comptime {
7362+
const opt_ptr: ?*i32 = null;
7363+
const ptr = @ptrCast(*i32, opt_ptr);
7364+
}
7365+
{#code_end#}
7366+
<p>At runtime:</p>
7367+
{#code_begin|exe_err#}
7368+
pub fn main() void {
7369+
var opt_ptr: ?*i32 = null;
7370+
var ptr = @ptrCast(*i32, opt_ptr);
7371+
}
7372+
{#code_end#}
7373+
{#header_close#}
7374+
73527375
{#header_close#}
73537376
{#header_open|Memory#}
73547377
<p>TODO: explain no default allocator in zig</p>
@@ -7439,6 +7462,7 @@ pub fn main() void {
74397462
{#code_end#}
74407463
{#see_also|String Literals#}
74417464
{#header_close#}
7465+
74427466
{#header_open|Import from C Header File#}
74437467
<p>
74447468
The {#syntax#}@cImport{#endsyntax#} builtin function can be used
@@ -7477,6 +7501,36 @@ const c = @cImport({
74777501
{#code_end#}
74787502
{#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
74797503
{#header_close#}
7504+
7505+
{#header_open|C Pointers#}
7506+
<p>
7507+
This type is to be avoided whenever possible. The only valid reason for using a C pointer is in
7508+
auto-generated code from translating C code.
7509+
</p>
7510+
<p>
7511+
When importing C header files, it is ambiguous whether pointers should be translated as
7512+
single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).
7513+
C pointers are a compromise so that Zig code can utilize translated header files directly.
7514+
</p>
7515+
<p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p>
7516+
<ul>
7517+
<li>Supports all the syntax of the other two pointer types.</li>
7518+
<li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}.
7519+
When a C pointer is implicitly casted to a non-optional pointer, safety-checked
7520+
{#link|Undefined Behavior#} occurs if the address is 0.
7521+
</li>
7522+
<li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked
7523+
{#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of
7524+
null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer
7525+
is unnecessary as one can use normal {#link|Optional Pointers#}.
7526+
</li>
7527+
<li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li>
7528+
<li>Supports comparison with integers.</li>
7529+
<li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
7530+
please!</li>
7531+
</ul>
7532+
{#header_close#}
7533+
74807534
{#header_open|Exporting a C Library#}
74817535
<p>
74827536
One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages

0 commit comments

Comments
 (0)