authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-20 17:11:07-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-21 20:43:42-05:00
log6b623b5ea2a811b54a2391f17081a8981fa733a5
tree618d46efdcde882789a966741eb7c82153bd3ba6
parentfd6020c4e26c5a1e3652c2f88ab4e668f6fc1dbc
signaturelock-open Commit is signed but in an unrecognized format.

update docs for null terminated stuff


1 files changed, 76 insertions(+), 31 deletions(-)

doc/langref.html.in+76-31
...@@ -546,7 +546,10 @@ pub fn main() void {...@@ -546,7 +546,10 @@ pub fn main() void {
546 {#header_close#}546 {#header_close#}
547 {#header_open|String Literals and Character Literals#}547 {#header_open|String Literals and Character Literals#}
548 <p>548 <p>
549 String literals are UTF-8 encoded byte arrays.549 String literals are single-item constant {#link|Pointers#} to null-terminated UTF-8 encoded byte arrays.
550 The type of string literals encodes both the length, and the fact that they are null-terminated,
551 and thus they can be {#link|coerced|Type Coercion#} to both {#link|Slices#} and
552 {#link|Null-Terminated Pointers#}. Dereferencing string literals converts them to {#link|Arrays#}.
550 </p>553 </p>
551 <p>554 <p>
552 Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as555 Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as
...@@ -558,20 +561,15 @@ const assert = @import("std").debug.assert;...@@ -558,20 +561,15 @@ const assert = @import("std").debug.assert;
558const mem = @import("std").mem;561const mem = @import("std").mem;
559562
560test "string literals" {563test "string literals" {
561 // In Zig a string literal is an array of bytes.564 const bytes = "hello";
562 const normal_bytes = "hello";565 assert(@typeOf(bytes) == *const [5]null u8);
563 assert(@typeOf(normal_bytes) == [5]u8);566 assert(bytes.len == 5);
564 assert(normal_bytes.len == 5);567 assert(bytes[1] == 'e');
565 assert(normal_bytes[1] == 'e');568 assert(bytes[5] == 0);
566 assert('e' == '\x65');569 assert('e' == '\x65');
567 assert('\u{1f4a9}' == 128169);570 assert('\u{1f4a9}' == 128169);
568 assert('💯' == 128175);571 assert('💯' == 128175);
569 assert(mem.eql(u8, "hello", "h\x65llo"));572 assert(mem.eql(u8, "hello", "h\x65llo"));
570
571 // A C string literal is a null terminated pointer.
572 const null_terminated_bytes = c"hello";
573 assert(@typeOf(null_terminated_bytes) == [*]const u8);
574 assert(null_terminated_bytes[5] == 0);
575}573}
576 {#code_end#}574 {#code_end#}
577 {#see_also|Arrays|Zig Test|Source Encoding#}575 {#see_also|Arrays|Zig Test|Source Encoding#}
...@@ -641,23 +639,6 @@ const hello_world_in_c =...@@ -641,23 +639,6 @@ const hello_world_in_c =
641 \\}639 \\}
642;640;
643 {#code_end#}641 {#code_end#}
644 <p>
645 For a multiline C string literal, prepend <code>c</code> to each {#syntax#}\\{#endsyntax#}:
646 </p>
647 {#code_begin|syntax#}
648const c_string_literal =
649 c\\#include <stdio.h>
650 c\\
651 c\\int main(int argc, char **argv) {
652 c\\ printf("hello world\n");
653 c\\ return 0;
654 c\\}
655;
656 {#code_end#}
657 <p>
658 In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const u8{#endsyntax#} and
659 has a terminating null byte.
660 </p>
661 {#see_also|@embedFile#}642 {#see_also|@embedFile#}
662 {#header_close#}643 {#header_close#}
663 {#header_close#}644 {#header_close#}
...@@ -1638,12 +1619,11 @@ comptime {...@@ -1638,12 +1619,11 @@ comptime {
1638 assert(message.len == 5);1619 assert(message.len == 5);
1639}1620}
16401621
1641// a string literal is an array literal1622// A string literal is a pointer to an array literal.
1642const same_message = "hello";1623const same_message = "hello".*;
16431624
1644comptime {1625comptime {
1645 assert(mem.eql(u8, message, same_message));1626 assert(mem.eql(u8, message, same_message));
1646 assert(@typeOf(message) == @typeOf(same_message));
1647}1627}
16481628
1649test "iterate over an array" {1629test "iterate over an array" {
...@@ -1799,6 +1779,26 @@ test "multidimensional arrays" {...@@ -1799,6 +1779,26 @@ test "multidimensional arrays" {
1799}1779}
1800 {#code_end#}1780 {#code_end#}
1801 {#header_close#}1781 {#header_close#}
1782
1783 {#header_open|Null-Terminated Arrays#}
1784 <p>
1785 The syntax {#syntax#}[N]null T{#endsyntax#} describes an array which has a null element at the
1786 index corresponding to {#syntax#}len{#endsyntax#}.
1787 </p>
1788 {#code_begin|test|null_terminated_array#}
1789const std = @import("std");
1790const assert = std.debug.assert;
1791
1792test "null terminated array" {
1793 const array = [_]u8 null {1, 2, 3, 4};
1794
1795 assert(@typeOf(array) == [4]null u8);
1796 assert(array.len == 4);
1797 assert(slice[4] == 0);
1798}
1799 {#code_end#}
1800 {#see_also|Null-Terminated Pointers|Null-Terminated Slices#}
1801 {#header_close#}
1802 {#header_close#}1802 {#header_close#}
18031803
1804 {#header_open|Vectors#}1804 {#header_open|Vectors#}
...@@ -2111,6 +2111,29 @@ test "allowzero" {...@@ -2111,6 +2111,29 @@ test "allowzero" {
2111}2111}
2112 {#code_end#}2112 {#code_end#}
2113 {#header_close#}2113 {#header_close#}
2114
2115 {#header_open|Null-Terminated Pointers#}
2116 <p>
2117 The syntax {#syntax#}[*]null T{#endsyntax#} describes a pointer that
2118 has a length determined by a sentinel null value. This provides protection
2119 against buffer overflow and overreads.
2120 </p>
2121 {#code_begin|exe_build_err#}
2122const std = @import("std");
2123
2124// This is also available as `std.c.printf`.
2125pub extern "c" fn printf(format: [*]null const u8, ...) c_int;
2126
2127pub fn main() anyerror!void {
2128 _ = printf("Hello, world!\n"); // OK
2129
2130 const msg = "Hello, world!\n";
2131 const non_null_terminated_msg: [msg.len]u8 = msg.*;
2132 _ = printf(&non_null_terminated_msg);
2133}
2134 {#code_end#}
2135 {#see_also|Null-Terminated Slices|Null-Terminated Arrays#}
2136 {#header_close#}
2114 {#header_close#}2137 {#header_close#}
21152138
2116 {#header_open|Slices#}2139 {#header_open|Slices#}
...@@ -2194,7 +2217,29 @@ test "slice widening" {...@@ -2194,7 +2217,29 @@ test "slice widening" {
2194}2217}
2195 {#code_end#}2218 {#code_end#}
2196 {#see_also|Pointers|for|Arrays#}2219 {#see_also|Pointers|for|Arrays#}
2220
2221 {#header_open|Null-Terminated Slices#}
2222 <p>
2223 The syntax {#syntax#}[]null T{#endsyntax#} is a slice which has a runtime known length
2224 and also guarantees a null value at the element indexed by the length. The type does not
2225 guarantee that there are no null elements before that. Null-terminated slices allow element
2226 access to the {#syntax#}len{#endsyntax#} index.
2227 </p>
2228 {#code_begin|test|null_terminated_slice#}
2229const std = @import("std");
2230const assert = std.debug.assert;
2231
2232test "null terminated slice" {
2233 const slice: []null const u8 = "hello";
2234
2235 assert(slice.len == 5);
2236 assert(slice[5] == 0);
2237}
2238 {#code_end#}
2239 {#see_also|Null-Terminated Pointers|Null-Terminated Arrays#}
2197 {#header_close#}2240 {#header_close#}
2241 {#header_close#}
2242
2198 {#header_open|struct#}2243 {#header_open|struct#}
2199 {#code_begin|test|structs#}2244 {#code_begin|test|structs#}
2200// Declare a struct.2245// Declare a struct.