Tam olarak nasıl göründüğünü, C ve UNIX'in sözcük atadığı kısaltılmış şekilde kullandığınızı varsayarsak, dizeleri çoğaltır :-)
Aslında ISO C standardının kendisinin bir parçası olmadığını (a) (bir POSIX olayı) unutmayın, etkili bir şekilde aşağıdaki kodla aynı şeyi yapar:
char *strdup(const char *src) {
char *dst = malloc(strlen (src) + 1); // Space for length plus nul
if (dst == NULL) return NULL; // No memory
strcpy(dst, src); // Copy the characters
return dst; // Return the new string
}
Diğer bir deyişle:
Eski dizeyi tutacak kadar bellek ayırmaya çalışır (artı dizenin sonunu işaretlemek için '\ 0' karakteri).
Tahsisi başarısız olursa, o setleri errno
için ENOMEM
ve iadeler NULL
hemen. Arasında ayarlanması errno
için ENOMEM
bir şeydir malloc
biz açıkça Biz bir aile odada yapmak gerek kalmaz POSIX'deki yapar strdup
. Eğer konum değil POSIX uyumlu, ISO C aslında varlığını zorunlu kılmaz ENOMEM
Ben buraya dahil değil bu yüzden (b) .
Aksi takdirde, ayırma işe yaradı, böylece eski dizeyi yeni dizgiye (c) kopyalayıp yeni adresi (arayanın bir noktada serbest bırakmaktan sorumlu olduğu) döndürüyoruz.
Bunun kavramsal tanım olduğunu unutmayın. Maaşlarına değer herhangi bir kütüphane yazarı, kullanılan belirli işlemciyi hedefleyen yoğun şekilde optimize edilmiş kod sağlamış olabilir.
(a) Bununla birlikte, str
küçük harflerle başlayan işlevler ve küçük harfler gelecekteki talimatlar için standart tarafından ayrılmıştır. Gönderen C11 7.1.3 Reserved identifiers
:
Her başlık, ilişkili alt maddesinde listelenen tüm tanımlayıcıları bildirir veya tanımlar ve * isteğe bağlı olarak ilişkili gelecekteki kitaplık yönergeleri alt maddesinde listelenen tanımlayıcıları bildirir veya tanımlar. **
İçin gelecekteki talimatlar string.h
şurada bulunabilir C11 7.31.13 String handling <string.h>
:
İle başlayan Fonksiyon isimleri str
, mem
veya wcs
bir küçük harf içinde bildirimleri eklenebilir <string.h>
başlığında.
Bu yüzden, güvende olmak istiyorsanız, muhtemelen başka bir şey demelisiniz.
(b) Değişiklik temel olarak aşağıdakilerle değiştirilecektir if (d == NULL) return NULL;
:
if (d == NULL) {
errno = ENOMEM;
return NULL;
}
(c) Bunun strcpy
amacını açıkça gösterdiğinden, bunun için kullandığımı unutmayın . Bazı uygulamalarda, memcpy
verilerin daha büyük parçalar halinde veya paralel olarak aktarılmasına izin verebileceğinden (zaten uzunluğunu zaten bildiğinizden) kullanmak daha hızlı olabilir. Ya da olmayabilir :-) Optimizasyon mantra # 1: "ölç, tahmin etme".
Her durumda, bu rotaya gitmeye karar verirseniz, şöyle bir şey yaparsınız:
char *strdup(const char *src) {
size_t len = strlen(src) + 1; // String plus '\0'
char *dst = malloc(len); // Allocate space
if (dst == NULL) return NULL; // No memory
memcpy (dst, src, len); // Copy the block
return dst; // Return the new string
}