AC string adalah array karakter yang diakhiri dengan terminator nol .
Semua karakter memiliki nilai tabel simbol. Terminator nol adalah nilai simbol 0
(nol). Ini digunakan untuk menandai akhir sebuah string. Ini diperlukan karena ukuran string tidak disimpan di mana pun.
Oleh karena itu, setiap kali Anda mengalokasikan ruang untuk string, Anda harus menyertakan ruang yang cukup untuk karakter terminator nol. Contoh Anda tidak melakukan ini, itu hanya mengalokasikan ruang untuk 5 karakter "hello"
. Kode yang benar adalah:
char str[6] = "hello";
Atau dengan kata lain, Anda dapat menulis kode self-documenting untuk 5 karakter plus 1 null terminator:
char str[5+1] = "hello";
Saat mengalokasikan memori untuk string secara dinamis saat dijalankan, Anda juga perlu mengalokasikan ruang untuk terminator nol:
char input[n] = ... ;
...
char* str = malloc(strlen(input) + 1);
Jika Anda tidak menambahkan terminator nol di akhir string, maka fungsi perpustakaan yang mengharapkan string tidak akan berfungsi dengan baik dan Anda akan mendapatkan bug "perilaku tidak terdefinisi" seperti keluaran sampah atau crash program.
Cara yang paling umum untuk menulis karakter null terminator di C adalah dengan menggunakan apa yang disebut "oktal urutan escape", tampak seperti ini: '\0'
. Ini 100% setara dengan menulis 0
, tetapi \
berfungsi sebagai kode yang mendokumentasikan diri untuk menyatakan bahwa nol secara eksplisit dimaksudkan sebagai terminator nol. Kode seperti itu if(str[i] == '\0')
akan memeriksa apakah karakter spesifiknya adalah terminator nol.
Harap dicatat bahwa istilah terminator nol tidak ada hubungannya dengan pointer nol atau NULL
makro! Ini bisa membingungkan - nama yang sangat mirip tetapi artinya sangat berbeda. Inilah sebabnya mengapa terminator nol kadang-kadang disebut NUL
dengan satu L, tidak menjadi bingung dengan NULL
atau null pointer. Lihat jawaban untuk pertanyaan SO ini untuk perincian lebih lanjut.
Dalam "hello"
kode Anda disebut string literal . Ini harus dianggap sebagai string hanya baca. The ""
sintaks berarti bahwa kompiler akan menambahkan sebuah nol terminator pada akhir string literal otomatis. Jadi jika Anda mencetak sizeof("hello")
Anda akan mendapatkan 6, bukan 5, karena Anda mendapatkan ukuran array termasuk terminator nol.
Kompilasi ini bersih dengan gcc
Bahkan bukan peringatan. Ini karena detail halus / cacat dalam bahasa C yang memungkinkan array karakter diinisialisasi dengan string literal yang berisi persis karakter sebanyak ada ruang dalam array dan kemudian diam-diam membuang terminator nol (C17 6.7.9 / 15). Bahasa ini sengaja berperilaku seperti ini untuk alasan historis, lihat diagnostik gcc tidak konsisten untuk inisialisasi string untuk detail. Perhatikan juga bahwa C ++ berbeda di sini dan tidak memungkinkan trik / cacat ini digunakan.
char str[] = "hello";
kopernya.char *str = "hello";
...str[0] = foo;
masalahnya.sizeof
penggunaannya pada parameter fungsi, terutama ketika didefinisikan sebagai sebuah array.Dari Standar C (7.1.1 Definisi istilah)
Dalam deklarasi ini
string literal
"hello"
memiliki representasi internal sepertisehingga memiliki 6 karakter termasuk nol penghentian. Elemen-elemennya digunakan untuk menginisialisasi array karakter
str
yang hanya menyediakan ruang untuk 5 karakter.Standar C (berseberangan dengan Standar C ++) memungkinkan inisialisasi array karakter ketika nol penghentian string literal tidak digunakan sebagai penginisialisasi.
Namun akibatnya array karakter
str
tidak mengandung string.Jika Anda ingin array akan berisi string Anda bisa menulis
atau hanya
Dalam kasus terakhir ukuran array karakter ditentukan dari jumlah inisialisasi string literal yang sama dengan 6.
sumber
Dapatkah semua string dianggap sebagai array karakter ( Ya ), dapatkah semua array karakter dianggap string ( Tidak ).
Kenapa tidak? dan mengapa itu penting?
Selain jawaban lain yang menjelaskan bahwa panjang string tidak disimpan di mana pun sebagai bagian dari string dan referensi ke standar di mana string didefinisikan, sisi lain adalah "Bagaimana fungsi C library menangani string?"
Sementara array karakter dapat menampung karakter yang sama, itu hanya array karakter kecuali karakter terakhir diikuti oleh karakter nul-terminating . Itu nul-mengakhiri karakter adalah apa yang memungkinkan array karakter dipertimbangkan (ditangani sebagai) string.
Semua fungsi dalam C yang mengharapkan string sebagai argumen mengharapkan urutan karakter akan diakhiri . Mengapa?
Ini ada hubungannya dengan cara semua fungsi string bekerja. Karena panjang tidak dimasukkan sebagai bagian dari array, fungsi string, pindai maju dalam array sampai karakter-nul (misalnya
'\0'
- setara dengan desimal0
) ditemukan. Lihat Tabel dan Deskripsi ASCII . Terlepas apakah Anda menggunakanstrcpy
,strchr
,strcspn
, dll .. Semua fungsi string bergantung pada nul-terminating karakter yang hadir untuk menentukan di mana akhir string yang.Perbandingan dua fungsi serupa dari
string.h
akan menekankan pentingnya karakter nul-terminating . Ambil contoh:The
strcpy
Fungsi hanya salinan byte darisrc
kedest
sampai nul-terminating karakter ditemukan jitustrcpy
di mana harus berhenti menyalin karakter. Sekarang ambil fungsi yang samamemcpy
:Fungsi melakukan operasi serupa, tetapi tidak mempertimbangkan atau memerlukan
src
parameter untuk menjadi string. Karenamemcpy
tidak dapat hanya memindai ke depan dalamsrc
menyalin bytedest
hingga karakter nul-terminating tercapai, itu memerlukan jumlah byte eksplisit untuk menyalin sebagai parameter ketiga. Parameter ketiga ini memberikanmemcpy
informasi ukuran yang samastrcpy
yang dapat diturunkan hanya dengan memindai ke depan sampai karakter nul-terminating ditemukan.(yang juga menekankan apa yang salah
strcpy
(atau fungsi apa pun yang mengharapkan string) jika Anda gagal menyediakan fungsi dengan string nul-dihentikan - ia tidak tahu di mana harus berhenti dan dengan senang hati akan berlomba melintasi seluruh segmen memori Anda menerapkan Perilaku Undefined sampai nul-karakter kebetulan ditemukan di suatu tempat di memori - atau Segmentation Fault terjadi)Itulah sebabnya fungsi yang mengharapkan string nul-dihentikan harus melewati string nul-dihentikan dan mengapa itu penting .
sumber
Secara intuitif ...
Pikirkan sebuah array sebagai variabel (menyimpan sesuatu) dan string sebagai nilai (dapat ditempatkan dalam variabel).
Mereka tentu bukan hal yang sama. Dalam kasus Anda, variabelnya terlalu kecil untuk menahan string, sehingga string terputus. ("string yang dikutip" dalam C memiliki karakter nol implisit di akhir.)
Namun dimungkinkan untuk menyimpan string dalam array yang jauh lebih besar dari string.
Perhatikan bahwa operator penugasan dan pembanding biasa (
=
==
<
dll.) Tidak berfungsi seperti yang Anda harapkan. Tetapistrxyz
keluarga fungsi cukup dekat, begitu Anda tahu apa yang Anda lakukan. Lihat FAQ C tentang string dan array .sumber