ada juga strdupa () (di perpustakaan GNU C), fungsi yang bagus yang mirip dengan strdup (), tetapi mengalokasikan memori pada stack. Program Anda tidak perlu membebaskan memori secara eksplisit seperti halnya dengan strdup (), itu akan dibebaskan secara otomatis ketika Anda keluar dari fungsi tempat strdupa () dipanggil
dmityugov
11
strdupaberbahaya dan tidak boleh digunakan kecuali Anda sudah menentukan bahwa strlenitu sangat kecil. Tapi kemudian Anda bisa menggunakan array ukuran tetap pada stack.
R .. GitHub BERHENTI MEMBANTU ICE
4
@slacker google translate tidak membantu ... Apa artinya strdup/ strdupaartinya dalam bahasa Polandia?
Seperti apa persisnya, dengan asumsi Anda terbiasa dengan cara disingkat di mana C dan UNIX memberikan kata-kata, duplikat string :-)
Ingatlah bahwa itu sebenarnya bukan bagian dari standar ISO C itu sendiri (a) (itu adalah hal POSIX), itu secara efektif melakukan hal yang sama seperti kode berikut:
char*strdup(constchar*src){char*dst = malloc(strlen (src)+1);// Space for length plus nulif(dst == NULL)return NULL;// No memory
strcpy(dst, src);// Copy the charactersreturn dst;// Return the new string}
Dengan kata lain:
Mencoba mengalokasikan cukup memori untuk menampung string lama (ditambah karakter '\ 0' untuk menandai akhir string).
Jika alokasi gagal, set errnoke ENOMEMdan NULLsegera kembali . Pengaturan errnoto ENOMEMadalah sesuatu yang mallocdilakukan di POSIX sehingga kita tidak perlu melakukannya secara eksplisit di strdup. Jika Anda tidak mematuhi POSIX, ISO C tidak benar-benar mengamanatkan keberadaan ENOMEMjadi saya belum memasukkannya di sini (b) .
Kalau tidak, alokasi berhasil jadi kami menyalin string lama ke string baru (c) dan mengembalikan alamat baru (yang penelepon bertanggung jawab untuk membebaskan di beberapa titik).
Ingatlah bahwa itu adalah definisi konseptual. Penulis perpustakaan mana pun yang sepadan dengan gajinya mungkin telah menyediakan kode yang sangat dioptimalkan yang menargetkan prosesor tertentu yang digunakan.
(a) Namun, fungsi yang dimulai dengan strdan huruf kecil disediakan oleh standar untuk arahan di masa mendatang. Dari C11 7.1.3 Reserved identifiers:
Setiap header menyatakan atau mendefinisikan semua pengidentifikasi yang tercantum dalam sub-klausa yang terkait, dan * secara opsional mendeklarasikan atau mendefinisikan pengidentifikasi yang tercantum dalam sub-klausa arah pustaka arah terkait di masa depan. **
Arahan masa depan untuk string.hdapat ditemukan di C11 7.31.13 String handling <string.h>:
Nama fungsi yang dimulai dengan str,, mematau wcsdan huruf kecil dapat ditambahkan ke deklarasi di <string.h>header.
Jadi Anda mungkin harus menyebutnya sesuatu yang lain jika Anda ingin aman.
(B) Perubahan pada dasarnya akan diganti if (d == NULL) return NULL;dengan:
if(d == NULL){
errno = ENOMEM;return NULL;}
(c) Perhatikan bahwa saya menggunakan strcpyuntuk itu karena itu jelas menunjukkan maksudnya. Dalam beberapa implementasi, mungkin lebih cepat (karena Anda sudah tahu panjangnya) untuk digunakanmemcpy , karena mereka memungkinkan untuk mentransfer data dalam potongan yang lebih besar, atau secara paralel. Atau mungkin tidak :-) Mantra pengoptimalan # 1: "ukur, jangan menebak".
Bagaimanapun, jika Anda memutuskan untuk pergi ke rute itu, Anda akan melakukan sesuatu seperti:
char*strdup(constchar*src){size_t len = strlen(src)+1;// String plus '\0'char*dst = malloc(len);// Allocate spaceif(dst == NULL)return NULL;// No memory
memcpy (dst, src, len);// Copy the blockreturn dst;// Return the new string}
Perlu dicatat, bahwa seperti implementasi sampel Pax menyiratkan, strdup (NULL) tidak terdefinisi dan bukan sesuatu yang dapat Anda harapkan untuk berperilaku dengan cara yang dapat diprediksi.
bersantai
2
Juga, saya pikir malloc () akan mengatur errno, jadi Anda tidak harus mengaturnya sendiri. Kupikir.
Chris Lutz
5
@Alcot, strdupuntuk situasi di mana Anda ingin menumpuk memori yang dialokasikan untuk salinan string. Kalau tidak, Anda harus melakukannya sendiri. Jika Anda sudah memiliki buffer yang cukup besar (malloc'ed atau sebaliknya), ya, gunakan strcpy.
paxdiablo
2
@acgtyrant: jika, menurut standar, maksud Anda standar ISO (standar C nyata), tidak, itu bukan bagian dari itu. Ini adalah bagian dari standar POSIX. Namun, ada banyak implementasi C yang menyediakannya, meskipun tidak menjadi bagian resmi dari ISO C. Namun, bahkan jika tidak, lima baris dalam jawaban ini harus lebih dari cukup.
paxdiablo
2
Poin bagus, @chux, mandat ISO hanya { EDOM, EILSEQ, ERANGE }sebagai kode kesalahan yang diperlukan. Telah memperbarui jawaban untuk akun ini.
paxdiablo
86
char* strdup(constchar* s){size_t len =1+strlen(s);char*p = malloc(len);return p ? memcpy(p, s, len): NULL;}
Mungkin kodenya sedikit lebih cepat daripada dengan strcpy()karena \0char tidak perlu dicari lagi (sudah ada dengan strlen()).
Terima kasih. Dalam implementasi pribadi saya, saya membuatnya bahkan "lebih buruk". return memcpy(malloc(len), s, len);karena saya lebih suka crash pada alokasi daripada NULLkegagalan alokasi.
Patrick Schlüter
3
@tristopia dereferencing NULLtidak harus macet; itu tidak terdefinisi. Jika Anda ingin memastikannya macet, tulis emallocpanggilan mana yang abortgagal.
Dave
Saya tahu itu, tetapi implementasi saya dijamin hanya berjalan di Solaris atau Linux (berdasarkan sifat aplikasi).
Patrick Schlüter
@tristopia: Ada baiknya kebiasaan melakukan hal-hal dengan cara terbaik. Biasakan menggunakan emallocbahkan jika itu tidak perlu di Solaris atau Linux sehingga Anda akan menggunakannya di masa depan ketika Anda menulis kode pada platform lain.
ArtOfWarfare
51
Tidak ada gunanya mengulangi jawaban lainnya, tetapi harap dicatat bahwa strdup()dapat melakukan apa pun yang diinginkan dari perspektif C, karena itu bukan bagian dari standar C apa pun. Namun demikian didefinisikan oleh POSIX.1-2001.
Apakah strdup()portable? Tidak, tidak tersedia di lingkungan non-POSIX (toh bisa diterapkan secara sepele). Tetapi untuk mengatakan fungsi POSIX dapat melakukan apa saja cukup bagus. POSIX adalah standar lain yang sebagus C dan bahkan lebih populer.
PP
2
@ BlueMoon Saya pikir intinya adalah bahwa implementasi C yang mengklaim tidak ada kesesuaian dengan POSIX mungkin masih menyediakan strdupfungsi sebagai ekstensi. Pada implementasi seperti itu, tidak ada jaminan bahwa strdupberperilaku dengan cara yang sama seperti fungsi POSIX. Saya tidak tahu implementasi semacam itu, tetapi implementasi tidak berbahaya yang sah dapat memberikan char *strdup(char *)alasan historis, dan menolak upaya untuk lulus dalam a const char *.
Apa perbedaan antara standar C dan POSIX? Maksudnya standar C, itu tidak ada di perpustakaan standar C?
Koray Tugay
@ KorayTugay Mereka adalah standar yang berbeda. Lebih baik memperlakukannya sebagai tidak terkait kecuali Anda tahu bahwa standar untuk fungsi C tertentu sesuai dengan standar POSIX, dan bahwa kompiler / pustaka Anda sesuai dengan standar untuk fungsi itu.
The strdup()fungsi akan kembali pointer ke string baru, yang merupakan duplikat dari string ditunjukkan oleh s1. Pointer yang dikembalikan dapat diteruskan ke free(). Pointer null dikembalikan jika string baru tidak dapat dibuat.
Jadi, apa yang dilakukannya adalah memberi kita string lain yang identik dengan string yang diberikan oleh argumennya, tanpa mengharuskan kita mengalokasikan memori. Tapi kita masih harus membebaskannya, nanti.
Itu membuat salinan duplikat dari string yang dilewatkan dengan menjalankan malloc dan strcpy dari string yang dilewatkan. Buffer malloc'ed dikembalikan ke pemanggil, maka kebutuhan untuk menjalankan bebas pada nilai kembali.
Hal paling berharga yang dilakukannya adalah memberi Anda string lain yang identik dengan yang pertama, tanpa mengharuskan Anda mengalokasikan memori (lokasi dan ukuran) sendiri. Tetapi, seperti yang disebutkan, Anda masih perlu membebaskannya (tetapi yang tidak memerlukan perhitungan kuantitas, juga.)
Jadi, jika Anda ingin string yang telah Anda salin digunakan di fungsi lain (seperti yang dibuat di bagian heap), Anda bisa menggunakan strdup, kalau strcpytidak cukup,
Fungsi strdup () adalah singkatan untuk duplikat string, mengambil parameter sebagai konstanta string atau string literal dan mengalokasikan ruang yang cukup untuk string dan menulis karakter yang sesuai dalam ruang yang dialokasikan dan akhirnya mengembalikan alamat yang dialokasikan ruang untuk rutinitas panggilan.
strdupa
berbahaya dan tidak boleh digunakan kecuali Anda sudah menentukan bahwastrlen
itu sangat kecil. Tapi kemudian Anda bisa menggunakan array ukuran tetap pada stack.strdup
/strdupa
artinya dalam bahasa Polandia?Jawaban:
Seperti apa persisnya, dengan asumsi Anda terbiasa dengan cara disingkat di mana C dan UNIX memberikan kata-kata, duplikat string :-)
Ingatlah bahwa itu sebenarnya bukan bagian dari standar ISO C itu sendiri (a) (itu adalah hal POSIX), itu secara efektif melakukan hal yang sama seperti kode berikut:
Dengan kata lain:
Mencoba mengalokasikan cukup memori untuk menampung string lama (ditambah karakter '\ 0' untuk menandai akhir string).
Jika alokasi gagal, set
errno
keENOMEM
danNULL
segera kembali . Pengaturanerrno
toENOMEM
adalah sesuatu yangmalloc
dilakukan di POSIX sehingga kita tidak perlu melakukannya secara eksplisit distrdup
. Jika Anda tidak mematuhi POSIX, ISO C tidak benar-benar mengamanatkan keberadaanENOMEM
jadi saya belum memasukkannya di sini (b) .Kalau tidak, alokasi berhasil jadi kami menyalin string lama ke string baru (c) dan mengembalikan alamat baru (yang penelepon bertanggung jawab untuk membebaskan di beberapa titik).
Ingatlah bahwa itu adalah definisi konseptual. Penulis perpustakaan mana pun yang sepadan dengan gajinya mungkin telah menyediakan kode yang sangat dioptimalkan yang menargetkan prosesor tertentu yang digunakan.
(a) Namun, fungsi yang dimulai dengan
str
dan huruf kecil disediakan oleh standar untuk arahan di masa mendatang. DariC11 7.1.3 Reserved identifiers
:Arahan masa depan untuk
string.h
dapat ditemukan diC11 7.31.13 String handling <string.h>
:Jadi Anda mungkin harus menyebutnya sesuatu yang lain jika Anda ingin aman.
(B) Perubahan pada dasarnya akan diganti
if (d == NULL) return NULL;
dengan:(c) Perhatikan bahwa saya menggunakan
strcpy
untuk itu karena itu jelas menunjukkan maksudnya. Dalam beberapa implementasi, mungkin lebih cepat (karena Anda sudah tahu panjangnya) untuk digunakanmemcpy
, karena mereka memungkinkan untuk mentransfer data dalam potongan yang lebih besar, atau secara paralel. Atau mungkin tidak :-) Mantra pengoptimalan # 1: "ukur, jangan menebak".Bagaimanapun, jika Anda memutuskan untuk pergi ke rute itu, Anda akan melakukan sesuatu seperti:
sumber
strdup
untuk situasi di mana Anda ingin menumpuk memori yang dialokasikan untuk salinan string. Kalau tidak, Anda harus melakukannya sendiri. Jika Anda sudah memiliki buffer yang cukup besar (malloc'ed atau sebaliknya), ya, gunakanstrcpy
.{ EDOM, EILSEQ, ERANGE }
sebagai kode kesalahan yang diperlukan. Telah memperbarui jawaban untuk akun ini.Mungkin kodenya sedikit lebih cepat daripada dengan
strcpy()
karena\0
char tidak perlu dicari lagi (sudah ada denganstrlen()
).sumber
return memcpy(malloc(len), s, len);
karena saya lebih suka crash pada alokasi daripadaNULL
kegagalan alokasi.NULL
tidak harus macet; itu tidak terdefinisi. Jika Anda ingin memastikannya macet, tulisemalloc
panggilan mana yangabort
gagal.emalloc
bahkan jika itu tidak perlu di Solaris atau Linux sehingga Anda akan menggunakannya di masa depan ketika Anda menulis kode pada platform lain.Tidak ada gunanya mengulangi jawaban lainnya, tetapi harap dicatat bahwa
strdup()
dapat melakukan apa pun yang diinginkan dari perspektif C, karena itu bukan bagian dari standar C apa pun. Namun demikian didefinisikan oleh POSIX.1-2001.sumber
strdup()
portable? Tidak, tidak tersedia di lingkungan non-POSIX (toh bisa diterapkan secara sepele). Tetapi untuk mengatakan fungsi POSIX dapat melakukan apa saja cukup bagus. POSIX adalah standar lain yang sebagus C dan bahkan lebih populer.strdup
fungsi sebagai ekstensi. Pada implementasi seperti itu, tidak ada jaminan bahwastrdup
berperilaku dengan cara yang sama seperti fungsi POSIX. Saya tidak tahu implementasi semacam itu, tetapi implementasi tidak berbahaya yang sah dapat memberikanchar *strdup(char *)
alasan historis, dan menolak upaya untuk lulus dalam aconst char *
.Dari strdup man :
The
strdup()
fungsi akan kembali pointer ke string baru, yang merupakan duplikat dari string ditunjukkan olehs1
. Pointer yang dikembalikan dapat diteruskan kefree()
. Pointer null dikembalikan jika string baru tidak dapat dibuat.sumber
strdup () melakukan alokasi memori dinamis untuk array karakter termasuk karakter akhir '\ 0' dan mengembalikan alamat memori tumpukan:
Jadi, apa yang dilakukannya adalah memberi kita string lain yang identik dengan string yang diberikan oleh argumennya, tanpa mengharuskan kita mengalokasikan memori. Tapi kita masih harus membebaskannya, nanti.
sumber
Itu membuat salinan duplikat dari string yang dilewatkan dengan menjalankan malloc dan strcpy dari string yang dilewatkan. Buffer malloc'ed dikembalikan ke pemanggil, maka kebutuhan untuk menjalankan bebas pada nilai kembali.
sumber
strdup
danstrndup
didefinisikan dalam sistem yang sesuai dengan POSIX sebagai:Fungsi strdup () mengalokasikan memori yang cukup untuk salinan string
str
, melakukan salinan, dan mengembalikan pointer ke sana.Pointer selanjutnya dapat digunakan sebagai argumen untuk fungsi
free
.Jika memori tidak mencukupi,
NULL
dikembalikan danerrno
disetel keENOMEM
.Fungsi strndup () menyalin paling banyak
len
karakter dari stringstr
selalu null mengakhiri string yang disalin.sumber
Hal paling berharga yang dilakukannya adalah memberi Anda string lain yang identik dengan yang pertama, tanpa mengharuskan Anda mengalokasikan memori (lokasi dan ukuran) sendiri. Tetapi, seperti yang disebutkan, Anda masih perlu membebaskannya (tetapi yang tidak memerlukan perhitungan kuantitas, juga.)
sumber
Pernyataan:
setara dengan (selain fakta ini mengubah pointer):
Sedangkan:
setara dengan:
Jadi, jika Anda ingin string yang telah Anda salin digunakan di fungsi lain (seperti yang dibuat di bagian heap), Anda bisa menggunakan
strdup
, kalaustrcpy
tidak cukup,sumber
Fungsi strdup () adalah singkatan untuk duplikat string, mengambil parameter sebagai konstanta string atau string literal dan mengalokasikan ruang yang cukup untuk string dan menulis karakter yang sesuai dalam ruang yang dialokasikan dan akhirnya mengembalikan alamat yang dialokasikan ruang untuk rutinitas panggilan.
sumber
strdup
tidak perlu berupa string konstan, harus berupa string C, yaitu array null yang dihentikanchar
.