str::as_mut_ptr¶
Level: reference · for working programmers
One line: The raw address of the first byte as *mut u8, from a &mut str — the writable counterpart of as_ptr.
Stable since 1.36.0. Usable in a const context.
Same pointer, with permission to write through it. That permission is the whole difficulty: str is not just bytes, it is bytes that are valid UTF-8, and writing through this pointer can break that. A &str whose bytes are not valid UTF-8 is undefined behaviour, not merely a wrong answer — every other method is entitled to assume the invariant holds.
Writing an ASCII byte over another ASCII byte is the one edit that is trivially safe, because every ASCII byte is a complete character. That is exactly what make_ascii_uppercase does, safely, and it is almost always the method you actually wanted.
Getting a &mut str at all is unusual — string literals are immutable, so it comes from String::as_mut_str or a &mut String coercion.
Example¶
str_as_mut_ptr.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let mut owned = String::from("hello");
// Safe, because ASCII -> ASCII is byte-for-byte and cannot break UTF-8.
let s: &mut str = owned.as_mut_str();
let p = s.as_mut_ptr();
unsafe { *p = b'H'; }
println!("{owned}");
// The safe spelling of the same edit.
let mut safe = String::from("hello");
safe.as_mut_str().make_ascii_uppercase();
println!("{safe}");
// Why it is unsafe: 'é' is two bytes, so overwriting one of them alone
// would leave the string invalid. Shown as a comment, not run.
let two_byte = String::from("é");
println!("'é' occupies {} bytes", two_byte.len());
}
Verified output of str_as_mut_ptr.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
str::as_ptr— the read-only counterpartstr::as_bytes_mut— the same permission, as a slicestr::make_ascii_uppercase— the safe in-place edit this is usually reaching forString::as_mut_str— where a&mut strcomes from
str::as_mut_ptr in the standard library ↗
Po polsku¶
Warto spojrzeć na sygnaturę: as_mut_ptr nie jest unsafe — samo pobranie surowego wskaźnika (raw pointer) niczego nie psuje, niebezpieczny jest dopiero zapis *p = …, i to w tym momencie przejmujesz obowiązek utrzymania niezmiennika typu str: bajty pod tym adresem muszą dalej być poprawnym UTF-8. Dlatego jedyną trywialnie bezpieczną edycją jest podmiana bajtu ASCII na inny bajt ASCII — é z przykładu zajmuje dwa bajty, dokładnie tak jak polskie ą, ł czy ż, więc nadpisanie jednego z nich osobno zostawia łańcuch znaków w stanie niedozwolonym. Osobna trudność pojawia się wcześniej: &mut str rzadko w ogóle się ma, bo literały są niemutowalne, i bierze się go z String::as_mut_str. Jeśli chodziło po prostu o zmianę wielkości liter w miejscu, właściwą odpowiedzią jest make_ascii_uppercase — bez unsafe i bez wskaźników.
Szukaj po polsku: surowy wskaźnik · mutowalny wycinek łańcucha · rust str as_mut_ptr · rust String as_mut_str · rust raw pointer undefined behavior