Mengapa String C Lambat dan Bagaimana Pointer Memperbaikinya

4

C tidak peduli dengan string. Tidak terlalu.

Ini memperlakukan mereka sebagai susunan karakter. Hanya byte dalam memori. Jika Anda ingin menggunakannya secara efektif, Anda memerlukan petunjuk. Bukan karena itu menyenangkan. Namun karena tanpa mereka, Anda melakukan pekerjaan ekstra.

Sebuah string di C hanyalah char str[100]. Itu terlihat seperti ruang untuk 100 karakter. Tidak. Ini ruang untuk 99 karakter ditambah terminator. C menggunakan string yang diakhiri dengan null. Setiap string diakhiri dengan nilai ASCII 0. Ditulis sebagai '\0'.

Ini mengubah segalanya.

Bahasa lain menangani string secara berbeda. Pascal menggunakan byte panjang. Ia tahu persis berapa banyak karakter yang disimpan. Tanya panjangnya? Ia mengembalikan byte itu. Segera.

C harus menghitung. Bunyinya sampai mencapai '\0'. Hal ini membuat C lebih lambat dalam beberapa kasus. Lebih cepat pada orang lain. Itu tergantung pada apa yang Anda lakukan.

Tidak ada dukungan string bawaan di C. Anda mengandalkan perpustakaan. menangani input dan output seperti gets dan puts. menangani manipulasi. Beberapa sistem menggunakan . Anda harus mengatur memori sendiri. Anda tidak bisa hanya menugaskan satu array ke array lainnya.

Itu saja. Anda menyalin elemen demi elemen. Atau Anda menggunakan strcpy. Fungsi perpustakaan melakukan pekerjaan berat.

strcpy ada di mana-mana di C. Ini menginisialisasi string. Ini menyalin data.

Setelah ini dijalankan, s1 menahan “halo” dan s2 menahan “halo”. Array menyimpan nilai ASCII. bilangan bulat. h adalah 104. e adalah 101. C berpikir dalam byte. Anda berpikir dalam teks. Mesin tidak peduli.

Perbandingan menggunakan strcmp. Ini mengembalikan bilangan bulat.

Nol berarti sama. Negatif berarti string pertama lebih kecil. Positif artinya lebih besar.

Fungsi lain ada. strlen mengembalikan panjang. strcat digabungkan. Baca halaman manual jika Anda membutuhkan lebih banyak.

Namun bagaimana sebenarnya fungsi-fungsi ini bekerja? Mari kita lihat strlen.

Pendekatan yang naif terlihat seperti ini:

Kebanyakan programmer C membenci ini. Tampaknya tidak efisien. Mereka lebih memilih petunjuk.

Anda dapat mengompresnya lebih lanjut.

Seorang ahli sejati mungkin bisa mempersingkatnya.

Saya mengkompilasi ini di MicroVAX dengan gcc. Tidak ada optimasi. Jalankan masing-masing 20.000 kali pada string 120 karakter.

Versi pertama: 12,3 detik.
Versi kedua: 12,3 detik.
Versi ketiga: 12,9 detik.

Pointer tidak selalu menang.

Tulis kode yang Anda pahami. Keterbacaan lebih penting daripada beberapa mikrodetik. Kecuali jika Anda berada dalam situasi yang sulit. Lalu mungkin optimalkan.

strcpy mengikuti evolusi serupa.

Mulailah dengan yang sudah jelas:

Perhatikan <=. Ini menyalin '\0'. Jika Anda melewatkannya, string tersebut tidak akan ada habisnya. Panjangnya tidak diketahui. Bug nanti. Sulit ditemukan.

Versi ini tidak efisien. strlen menjalankan setiap iterasi. Sebut saja sekali.

Sekarang petunjuk.

Kompres.

Bersih. Cepat. Berbahaya jika Anda tidak memeriksa batasannya.

Begitulah cara kerja string C. Tidak ada keajaiban. Hanya memori dan petunjuk. Dan banyak perhitungan yang cermat.

Pointer vs. Performa di strcpy

Secara teknis Anda dapat menulis ** while (s1++ = s2++);** untuk menangani penyalinan string. Kesenjangan kinerja antara implementasi yang naif dan implementasi yang dioptimalkan sangatlah mengejutkan.

Ambil strcpy. Versi pertama membutuhkan 415 detik untuk menyalin string 120 karakter sebanyak 10.000 kali. Versi kedua? 14,5 detik. Yang ketiga turun menjadi 9,8 detik. Yang keempat diselesaikan pada 10,3 detik.

Itu bukanlah perbedaan yang kecil. Ini merupakan dorongan besar. Pointer memberikan kecepatan di sini karena menghindari overhead yang tidak perlu.

Tipe Pengembalian dan Penunjuk String

Prototipe strcpy di pustaka string mengungkapkan maksudnya:

Kebanyakan fungsi string mengembalikan pointer ke string. strcpy mengembalikan nilai s1 sebagai hasilnya. Hal ini memungkinkan operasi rangkaian atau penggunaan langsung string yang disalin tanpa pencarian kedua.

Menghapus Bagian Depan Tanpa Memindahkan Data

Menggunakan pointer dengan string sering kali menghasilkan peningkatan kecepatan yang pasti. Anda dapat memanfaatkannya jika Anda memikirkannya sedikit.

Misalkan Anda ingin menghapus bagian depan yang kosong dari sebuah string. Nalurinya adalah menggeser karakter, menimpa bagian yang kosong. Di C, Anda dapat menghindari pergerakan sama sekali.

Ini jauh lebih cepat dibandingkan teknik gerakan. Terutama untuk string yang panjang. Anda tidak memindahkan byte. Anda baru saja mengubah penunjuk awal. Datanya tetap ada. Outputnya berubah.

Mengambil Trik

Anda akan mempelajari banyak trik lain dengan string seiring berjalannya waktu. Anda akan membaca kode lainnya. Anda akan melihat bagaimana orang lain menangani memori.

Latihan adalah kuncinya. Tidak ada jalan pintas untuk membaca kode. Anda hanya perlu melihat cara kerjanya dan memahami mengapa ini berhasil. Peningkatan kinerjanya nyata. Kurva pembelajarannya curam. Namun hasilnya berbicara sendiri.