| ... | ... | @@ -546,7 +546,10 @@ pub fn main() void { |
| 546 | 546 | {#header_close#} |
| 547 | 547 | {#header_open|String Literals and Character Literals#} |
| 548 | 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 | 553 | </p> |
| 551 | 554 | <p> |
| 552 | 555 | Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as |
| ... | ... | @@ -558,20 +561,15 @@ const assert = @import("std").debug.assert; |
| 558 | 561 | const mem = @import("std").mem; |
| 559 | 562 | |
| 560 | 563 | test "string literals" { |
| 561 | | // In Zig a string literal is an array of bytes. |
| 562 | | const normal_bytes = "hello"; |
| 563 | | assert(@typeOf(normal_bytes) == [5]u8); |
| 564 | | assert(normal_bytes.len == 5); |
| 565 | | assert(normal_bytes[1] == 'e'); |
| 564 | const bytes = "hello"; |
| 565 | assert(@typeOf(bytes) == *const [5]null u8); |
| 566 | assert(bytes.len == 5); |
| 567 | assert(bytes[1] == 'e'); |
| 568 | assert(bytes[5] == 0); |
| 566 | 569 | assert('e' == '\x65'); |
| 567 | 570 | assert('\u{1f4a9}' == 128169); |
| 568 | 571 | assert('💯' == 128175); |
| 569 | 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 | 574 | {#code_end#} |
| 577 | 575 | {#see_also|Arrays|Zig Test|Source Encoding#} |
| ... | ... | @@ -641,23 +639,6 @@ const hello_world_in_c = |
| 641 | 639 | \\} |
| 642 | 640 | ; |
| 643 | 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#} |
| 648 | | const 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 | 642 | {#see_also|@embedFile#} |
| 662 | 643 | {#header_close#} |
| 663 | 644 | {#header_close#} |
| ... | ... | @@ -1638,12 +1619,11 @@ comptime { |
| 1638 | 1619 | assert(message.len == 5); |
| 1639 | 1620 | } |
| 1640 | 1621 | |
| 1641 | | // a string literal is an array literal |
| 1642 | | const same_message = "hello"; |
| 1622 | // A string literal is a pointer to an array literal. |
| 1623 | const same_message = "hello".*; |
| 1643 | 1624 | |
| 1644 | 1625 | comptime { |
| 1645 | 1626 | assert(mem.eql(u8, message, same_message)); |
| 1646 | | assert(@typeOf(message) == @typeOf(same_message)); |
| 1647 | 1627 | } |
| 1648 | 1628 | |
| 1649 | 1629 | test "iterate over an array" { |
| ... | ... | @@ -1799,6 +1779,26 @@ test "multidimensional arrays" { |
| 1799 | 1779 | } |
| 1800 | 1780 | {#code_end#} |
| 1801 | 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#} |
| 1789 | const std = @import("std"); |
| 1790 | const assert = std.debug.assert; |
| 1791 | |
| 1792 | test "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 | 1802 | {#header_close#} |
| 1803 | 1803 | |
| 1804 | 1804 | {#header_open|Vectors#} |
| ... | ... | @@ -2111,6 +2111,29 @@ test "allowzero" { |
| 2111 | 2111 | } |
| 2112 | 2112 | {#code_end#} |
| 2113 | 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#} |
| 2122 | const std = @import("std"); |
| 2123 | |
| 2124 | // This is also available as `std.c.printf`. |
| 2125 | pub extern "c" fn printf(format: [*]null const u8, ...) c_int; |
| 2126 | |
| 2127 | pub 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 | 2137 | {#header_close#} |
| 2115 | 2138 | |
| 2116 | 2139 | {#header_open|Slices#} |
| ... | ... | @@ -2194,7 +2217,29 @@ test "slice widening" { |
| 2194 | 2217 | } |
| 2195 | 2218 | {#code_end#} |
| 2196 | 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#} |
| 2229 | const std = @import("std"); |
| 2230 | const assert = std.debug.assert; |
| 2231 | |
| 2232 | test "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 | 2240 | {#header_close#} |
| 2241 | {#header_close#} |
| 2242 | |
| 2198 | 2243 | {#header_open|struct#} |
| 2199 | 2244 | {#code_begin|test|structs#} |
| 2200 | 2245 | // Declare a struct. |