The reason why strings behave like this is because of interning. The variable is allowed to be mutable because it contains a pointer, so, in theory, you could make it point to another string (but not modify the string itself, since multiple vars might refer to the same bytes).
In this case Zig is mainly giving you insight into a process that is present in pretty much all languages.
constg=44;vargp=&g;
This one is Zig-specific, I believe. Since you're not specifying the type of g, you get comptime_int, which pulls you into the semantics of comptime evaluation. I believe that in stage2 you will be able to take a pointer from a comptime_int, but I'm actually not sure. In other words, this second case is the result of admittedly not-well-defined semantics in the language, but also you most probably want to specify a runtime type for any value that you want the pointer of. Note that during compilation comptime_ints are BigInts internally, meaning that taking their pointer is not a basic operation and the compiler must come up with its own design to avoid leaking that implementation detail.
Thanks for the reply !
The Zig specific behaviour of comptime_int makes more sense , but for strings I can still do var input = "Hello Zig".* and then modify it to something like input[0] = 'a' and input actually changes to aello Zig. What happens in this case?
Does Zig create a copy of Hello Zig on the stack, or does it create a completely new String and then modified that ?
"Hello Zig" is a chunk of memory inside the .rodata of your executable (or something of that sort, I believe different architecture-specific backends can decide where this stuff goes). So when you assing it to a variable, you get a pointer to those bytes.
When you dereference the pointer you get the full array contents which, yes, get copied to stack memory (assuming we're inside a function) and that then you can modify, since that memory is yours. If you look at the types it's very clear and consistent (if you know about string interning).
varstr_ptr="hi";// type: *const [2:0]u8vara=str_ptr.*;// type: [2:0]u8 varb=[2:0]u8{'y','o'};// type: same as `a`a=&b;// allowed since `b`'s type matches and `a` is var
When you dereference the pointer you get the full array contents which, yes, get copied to stack memory (assuming we're inside a function) and that then you can modify, since that memory is yours
Ok, this is the context I was missing (basically dereferring "x".*) creates a copy on the Stack that I can then modify. Thanks !
For further actions, you may consider blocking this person and/or reporting abuse
The reason why strings behave like this is because of interning. The variable is allowed to be mutable because it contains a pointer, so, in theory, you could make it point to another string (but not modify the string itself, since multiple vars might refer to the same bytes).
In this case Zig is mainly giving you insight into a process that is present in pretty much all languages.
This one is Zig-specific, I believe. Since you're not specifying the type of
g
, you getcomptime_int
, which pulls you into the semantics of comptime evaluation. I believe that in stage2 you will be able to take a pointer from acomptime_int
, but I'm actually not sure. In other words, this second case is the result of admittedly not-well-defined semantics in the language, but also you most probably want to specify a runtime type for any value that you want the pointer of. Note that during compilationcomptime_int
s are BigInts internally, meaning that taking their pointer is not a basic operation and the compiler must come up with its own design to avoid leaking that implementation detail.Thanks for the reply !
The Zig specific behaviour of
comptime_int
makes more sense , but for strings I can still dovar input = "Hello Zig".*
and then modify it to something likeinput[0] = 'a'
and input actually changes toaello Zig
. What happens in this case?Does Zig create a copy of
Hello Zig
on the stack, or does it create a completely new String and then modified that ?"Hello Zig"
is a chunk of memory inside the.rodata
of your executable (or something of that sort, I believe different architecture-specific backends can decide where this stuff goes). So when you assing it to a variable, you get a pointer to those bytes.When you dereference the pointer you get the full array contents which, yes, get copied to stack memory (assuming we're inside a function) and that then you can modify, since that memory is yours. If you look at the types it's very clear and consistent (if you know about string interning).
Ok, this is the context I was missing (basically dereferring "x".*) creates a copy on the Stack that I can then modify. Thanks !