From d0c39895aae085e421ada85d9d07f417d549c7e6 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
In this function, values {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are known only at runtime,
- and thus this division operation is vulnerable to both integer overflow and
- division by zero.
+ and thus this division operation is vulnerable to both {#link|Integer Overflow#} and
+ {#link|Division by Zero#}.
Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and
{#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.
+ Zig supports arbitrary bit-width integers, referenced by using
+ an identifier of Pointers work at compile-time too, as long as the code does not depend on
+ Pointers work at compile-time too, as long as the code does not depend on
an undefined memory layout: {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout. TODO bit fields TODO alignment TODO endianness TODO @bitOffsetOf and @byteOffsetOf TODO mention how volatile loads and stores of bit packed fields could be more efficient when
- done by hand instead of with packed struct
+ Unlike normal structs, {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout:
+
+ This means that a {#syntax#}packed struct{#endsyntax#} can participate
+ in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.
+ This even works at {#link|comptime#}:
+
+ Zig allows the address to be taken of a non-byte-aligned field:
+
+ However, the pointer to a non-byte-aligned field has special properties and cannot
+ be passed when a normal pointer is expected:
+
+ In this case, the function {#syntax#}bar{#endsyntax#} cannot be called becuse the pointer
+ to the non-byte-aligned field mentions the bit offset, but the function expects a byte-aligned pointer.
+
+ Pointers to non-byte-aligned fields share the same address as the other fields within their host integer:
+
+ This can be observed with {#link|@bitOffsetOf#} and {#link|byteOffsetOf#}:
+
+ Packed structs have 1-byte alignment. However if you have an overaligned pointer to a packed struct,
+ Zig should correctly understand the alignment of fields. However there is
+ a bug:
+ When this bug is fixed, the above test in the documentation will unexpectedly pass, which will
+ cause the test suite to fail, notifying the bug fixer to update these docs.
+
+ It's also
+ planned to be able to set alignment of struct fields.
+
+ Using packed structs with {#link|volatile#} is problematic, and may be a compile error in the future.
+ For details on this subscribe to
+ this issue.
+ TODO update these docs with a recommendation on how to use packed structs with MMIO
+ (the use case for volatile packed structs) once this issue is resolved.
+ Don't worry, there will be a good solution for this use case in zig.
+ Since all structs are anonymous, Zig infers the type name based on a few rules. By default, the size of enums is not guaranteed. {#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the integer tag type
- of the enum: {#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the
+ integer tag type of the enum: This makes the enum eligible to be in a {#link|packed struct#}.i
or u followed by digits. For example, the identifier
+ {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
+ integer type is {#syntax#}65535{#endsyntax#}.
+
+
+
A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible + to be in a {#link|packed struct#}. {#header_close#} + {#header_close#} + {#header_open|blocks#}
Blocks are used to limit the scope of variable declarations: @@ -3771,7 +3967,7 @@ fn bang2() void { Here, the stack trace does not explain how the control flow in {#syntax#}bar{#endsyntax#} got to the {#syntax#}hello(){#endsyntax#} call. One would have to open a debugger or further instrument the application - in order to find out. The error return trace, on the other hand, + in order to find out. The error return trace, on the other hand, shows exactly how the error bubbled up.
@@ -3963,7 +4159,7 @@ test "optional type" { cast it to a different type:
{#code_begin|syntax#} -const optional_value: ?i32 = null; +const optional_value: ?i32 = null; {#code_end#} {#header_close#} {#header_open|Optional Pointers#} @@ -5141,7 +5337,7 @@ async fn testResumeFromSuspend(my_result: *i32) void {{#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes as an operand a promise handle. - If the async function associated with the promise handle has already returned, + If the async function associated with the promise handle has already returned, then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value. Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its promise handle with the target coroutine. It becomes the target coroutine's responsibility @@ -5225,7 +5421,7 @@ fn seq(c: u8) void { {#header_close#} - + {#header_close#} {#header_open|Builtin Functions#}
@@ -5580,13 +5776,13 @@ const warn = @import("std").debug.warn; const num1 = blk: { var val1: i32 = 99; - @compileLog("comptime val1 = ", val1); + @compileLog("comptime val1 = ", val1); val1 = val1 + 1; break :blk val1; }; test "main" { - @compileLog("comptime in main"); + @compileLog("comptime in main"); warn("Runtime in main, num1 = {}.\n", num1); } @@ -5596,10 +5792,10 @@ test "main" { will ouput:
- If all {#syntax#}@compileLog{#endsyntax#} calls are removed or + If all {#syntax#}@compileLog{#endsyntax#} calls are removed or not encountered by analysis, the program compiles successfully and the generated executable prints: -
+ {#code_begin|test#} const warn = @import("std").debug.warn; @@ -6425,7 +6621,7 @@ fn List(comptime T: type) type {When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the current import. There is a proposal to remove the import type and use an empty struct - type instead. See + type instead. See #1047 for details.
{#header_close#} @@ -7560,7 +7756,7 @@ const c = @cImport({ {#link|Undefined Behavior#} occurs if the address is 0.