Is the following code good?
const std = @import("std");
const T = struct{
fn bar(_: *T) void {}
};
fn Foo() *T {
var t = T{};
return &t; // safe or not?
}
pub fn main() !void {
const t = Foo();
t.bar();
}
Is the following code good?
const std = @import("std");
const T = struct{
fn bar(_: *T) void {}
};
fn Foo() *T {
var t = T{};
return &t; // safe or not?
}
pub fn main() !void {
const t = Foo();
t.bar();
}
The pointer is dangling, but derefences will probably get optimized away (?) so it doesn’t matter.
I wouldn’t call it “good” in any case
There’s no state you need here anyway, so you can just write:
const std = @import("std");
const T = struct{
fn bar() void {}
};
pub fn main() !void {
T.bar();
}
(Might not be the exact point here, but yeah)
Also, &.{}
is acceptable for an empty struct/slice constant (but note that it’s been replaced in the stdlib wiith .empty
semantics). But if you just need namespacing, use the above example.
Well, there are no dereferences in the first place, only pointer copies, so I guess the code is technically fine… But I don’t really understand the utility of doing this. Should @zigo add any fields to the struct in the future and use them, a lot of code may become invalid and possibly hard to debug.
Looks like a good use case for making the return pointer an optional.
Sometimes, 3rd-party lib APIs need a anytype
argument which is required to be a pointer.
For this use case, I think it is much better to pass &@as(T, .{})
in directly
Is the value of &@as(T, .{})
still valid after the caller function exits?
Every time when passing parameters, using this expression directly is logically equivalent to always creating a new empty structure, without the need to pass this reference elsewhere.
Why do you want to do this? Your previous replies haven’t really clarified this.
Some 3rd-party lib APIs might need a anytype
argument which is required to be a pointer. And I don’t want to use allocators or global variables.
Yes, it’s safe. Pointers to empty structs always point to the same address. Derefencing it is a no-op.
But, as has been mentioned, it’s a footgun, as if you later add a field to it, you’re going to have undefined behaviour which could be hard to find.