-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider adding CString/*const i8 literals #400
Comments
You can get close with a macro using macro_rules! c_str {
($s:expr) => { {
concat!($s, "\0").as_ptr() as *const i8
} }
}
foo(c_str!("my string")); Doesn't look too bad imo. A limitation is that you can't initialize statics like that right now. Maybe there's some cast trickery to make that work but I haven't been able to figure that out. |
Why not null-terminate the literals by default? It wouldn't affect Rust code at all. |
We used to null-terminate strings. It didn't really work, since any slice of a string that doesn't include the end will not be null terminated. |
That macro would be nice to have in the standard library. |
Rather than adding more magic syntax, why not add a trait similar to Haskell's IsString (used with overloaded string literals)? Then, "string" would mean fromString("string"). |
@joshtriplett #143 proposed adding overloaded string literals, but was postponed. |
I've created a compiler plugin which achieves this, piggy-backing on the binary strings (which must be used in place of regular strings). It's my first attempt at a plugin and I'm pretty much a beginner at Rust too so I may be doing something hideous, but it works for me. It requires Using the plugin I have confirmed through LLVM-IR that the code compiles to the most obvious traditional C implementation. The usage syntax is just #![feature(libc, plugin)]
#![plugin(c_str)]
extern crate libc;
fn main()
{
unsafe { libc::puts(c!(b"Hello, World!")); }
} It would be ideal if this could just be available as suggested as a |
You do not even need a compiler plugin by doing something along the lines of: macro_rules! c {
($str: expr) => {
concat!($str, "\0") as *const u8
}
} EDIT: I as always didn’t read backlog and there was a similar macro up there already at #400 (comment). |
There's a missing |
That’s a fair point which would be resolved by #1187.
|
Any solution would be fine, but since this issue has languished for nearly 12 months I thought I'd share what I'd been using as a workaround for other people tripped up by it. |
It turns out my attempted implementation was naive, and I cannot work out if the problem is hard because I don't know what I'm doing, or if there just isn't any way to do it. I cannot find any way to cast a Forgetting the issue of the null termination which it is apparent is already quite solvable, how do I get a statically bound reference (either |
This seems to work: const P: *const i8 = &b"test\0"[0] as *const u8 as *const i8; |
@Kimundi what you have suggested compiles but results in undefined behaviour. It stores just the first character of the string and then takes the address of it and the rest is discarded.
|
Hrmmm... |
The Erlang NIF loading machinery cannot let Rust allocate a properly NUL-terminated string beforehand, except by leaking memory when the NIF is unloaded. This all comes from the lack of NUL-terminated string literal. erlang/otp#1294 (comment) |
@canndrew macro_rules! cstr {
($s:expr) => (
concat!($s, "\0") as *const str as *const [c_char] as *const c_char
);
} |
I guess so. I'd long forgotten about this ancient bug. Edit: I can't close it though |
|
There is no such constraint, no. A byte string literal may contain all
bytes from 0 to 256, although some of the bytes might require escape
sequences to express.
…On Nov 22, 2017 3:40 AM, "Anthony Ramine" ***@***.***> wrote:
b"my string\0" has the additional constraint that it cannot contain
non-ASCII bytes, and we still cannot concat byte literals AFAIK.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#400 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AApc0j-1dIN5Os8QtbLYd5OC8-5RyYT-ks5s43uVgaJpZM4CvKv_>
.
|
OH, thanks @nagisa I had never realised that wow. |
Issue by canndrew
Wednesday Oct 15, 2014 at 15:59 GMT
For earlier discussion, see rust-lang/rust#18065
This issue was labelled with: B-RFC, I-enhancement in the Rust repository
There's already
b"foo"
syntax for[u8]
literals and I've seen talk of addings"foo"
forString
literals (perhaps through a syntax extension). If we're going down that path we could also addc"foo"
syntax which could be either aCString
or a*const i8
. This would be useful for interacting with foreign C code. Currently, to call a C function with a string constant I'm usingBut that's a little cumbersome (and error-prone if I accidentally leave the NUL off).
The text was updated successfully, but these errors were encountered: