CodeBlanks Logo Icon CodeBlanks

CString ve CStr

CString ve CStr ile C string dönüşümü yaparsın.

CString ve CStr

C dizeleri boş bayt (\0) ile biten bayt dizileridir; Rust dizeleri ise uzunluğunu bilir ve içinde \0 olabilir. Köprü iki türdür:

  • CString: sahip olunan, sonu \0 ile biten dize; Rust'tan C'ye göndermek için.
  • CStr: ödünç alınmış C dizesi; C'den gelen işaretçiyi okumak için.
use std::ffi::{CStr, CString};

let c = CString::new("merhaba").unwrap();
let n = unsafe { strlen(c.as_ptr()) };      // 7

let s = CStr::from_bytes_with_nul(b"rust\0").unwrap();
println!("{}", s.to_str().unwrap());        // rust

Sık yapılan hata: sarkan işaretçi

as_ptr ile alınan işaretçi yalnızca CString yaşadığı sürece geçerlidir. Geçici bir değerden işaretçi almak sarkan işaretçi üretir:

// YANLIŞ: CString hemen bırakılır, p geçersiz kalır
let p = CString::new("x").unwrap().as_ptr();

// DOĞRU: önce değişkene bağla
let c = CString::new("x").unwrap();
let p = c.as_ptr();   // c yaşadıkça geçerli

Sahipliği C'ye devretmek için into_raw, geri almak için CString::from_raw kullanılır.

Uygulama C dizeleri

C'nin strlen fonksiyonunu bildir. CString::new("merhaba") uzunluğunu strlen ile al; CStr::from_bytes_with_nul(b"rust\0") değerini &str'ye çevir; CString::new("a\0b").is_err() sonucunu bul. Üçünü boşlukla yazdır.

Başlangıç kodu

main.rs
use std::ffi::{c_char, CStr, CString};

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
use std::ffi::{c_char, CStr, CString};

unsafe extern "C" {
    fn strlen(s: *const c_char) -> usize;
}

fn main() {
    let c = CString::new("merhaba").unwrap();
    // SAFETY: c geçerli, sonu boş baytla biten bir dizedir.
    let n = unsafe { strlen(c.as_ptr()) };
    let s = CStr::from_bytes_with_nul(b"rust\0").unwrap();
    let hata = CString::new("a\0b").is_err();
    println!("{} {} {}", n, s.to_str().unwrap(), hata);
}

Beklenen çıktı

7 rust true

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 <code>CString::new("a\0b")</code> neden hata verir?

  • b geçersiz
  • Çok kısa
  • Hata vermez
  • İçteki \0, C tarafında dizeyi erken bitirirdi Doğru cevap

Açıklama: CString::new içte boş bayt bulursa NulError döndürür; böylece sessiz kesilme önlenir.

2 C dizesi oluştur

Soru
let c = ____::new("merhaba").unwrap();
let n = unsafe { strlen(c.as_ptr()) };
Cevap
let c = CString::new("merhaba").unwrap();
let n = unsafe { strlen(c.as_ptr()) };

Açıklama: CString Rust'tan C'ye dize göndermek içindir.

3 Tür ve yönü

Kavram Anlamı
CString Rust → C (sahip)
CStr C → Rust (ödünç)
as_ptr() *const c_char
into_raw() Sahipliği C'ye ver

İleri seviye bölümündeki tüm dersler