İlk başta daha sonra olduğundan daha korkunç görünen her şeyde olduğu gibi, ilk korkuyu aşmanın en iyi yolu kendinizi bilinmeyenin rahatsızlığına kaptırmaktır ! Ne de olsa bazen en çok öğrendiğimiz şeydir.
Maalesef sınırlamalar var. Hâlâ bir işlevi kullanmayı öğrenirken, örneğin bir öğretmen rolünü üstlenmemelisiniz. Görünüşe göre nasıl kullanılacağını bilmeyenlerin realloc(yani şu anda kabul edilen cevap! ) Başkalarına yanlış bir şekilde nasıl kullanacaklarını söyleyen cevaplarını sık sık okurum, bu yaygın bir tuzak olmasına rağmen, bazen hata işlemeyi ihmal ettikleri kisvesi altında. bahsetmesi gereken. İşte nasıl kullanılacağını açıklayan bir cevap değil reallocdoğru . Hata kontrolü yapmak için cevabın dönüş değerini farklı bir değişkene kaydettiğine dikkat edin .
Bir işlevi her çağırdığınızda ve bir diziyi her kullandığınızda, bir işaretçi kullanırsınız. Dönüşümler örtük olarak gerçekleşiyor, bu da daha da korkutucu olmalı, çünkü genellikle en çok soruna neden olan, görmediğimiz şeylerdir. Örneğin bellek sızıntıları ...
Dizi operatörleri işaretçi operatörleridir. array[x]gerçekten bir kısayol *(array + x)olup, şu şekilde ayrılabilir: *ve (array + x). Büyük ihtimalle *kafanızı karıştıran şey budur. Biz ayrıca varsayarak problemden eklenmesini ortadan kaldırabilir xolmak 0, böylece array[0]olur *arrayekleyerek çünkü 0değerini değiştirmeyecektir ...
... ve böylece bunun *arrayeşdeğer olduğunu görebiliriz array[0]. Birini kullanmak istediğiniz yerde kullanabilirsiniz ve bunun tersi de geçerlidir. Dizi operatörleri işaretçi operatörleridir.
malloc, reallocVe arkadaşlar yok icat Eğer baştan beri kullanıyorum bir işaretçi kavramını; bunu yalnızca , boyutta şiddetli, dinamik değişiklikler istediğinizde en uygun olan, farklı bir depolama süresi biçimi olan başka bir özelliği uygulamak için kullanırlar .
Şu anda kabul edilen cevap bu utanç verici , aynı zamanda bir ters geliyor StackOverflow'daki diğer bazı çok sağlam temellere dayanan tavsiye ve aynı zamanda, tam da bu USECASE parlar az bilinen bir özelliği tanıtmak için bir fırsat kaçırır: Esnek dizi üyeler! Bu aslında oldukça bozuk bir cevap ... :(
Dizinizi tanımladığınızda, üst sınır olmadan yapının sonundastruct dizinizi bildirin. Örneğin:
struct int_list {
size_t size;
int value[];
};
Bu, dizinizi kendinizle intaynı ayırmada birleştirmenize olanak tanır countve bunların bu şekilde bağlanması çok kullanışlı olabilir !
sizeof (struct int_list)value0 boyutuna sahipmiş gibi davranacak , bu yüzden size yapının boyutunu boş bir liste ile söyleyecektir . reallocListenizin boyutunu belirtmek için geçilen boyutu yine de eklemeniz gerekir .
Başka bir kullanışlı ipucu da realloc(NULL, x)bunun eşdeğer olduğunu hatırlamaktır malloc(x)ve bunu kodumuzu basitleştirmek için kullanabiliriz. Örneğin:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->size = y;
return 0;
}
struct int_list *array = NULL;
struct int_list **İlk argüman olarak kullanmayı seçmemin nedeni hemen açık görünmeyebilir, ancak ikinci argümanı düşünürseniz value, içeriden yapılan herhangi bir değişiklik, push_backçağırdığımız fonksiyon tarafından görünmez, değil mi? Aynısı ilk argüman için de geçerli ve bizim arraysadece burada değil, aynı zamanda muhtemelen onu aktardığımız diğer fonksiyonlarda da değiştirebilmeliyiz ...
arrayhiçbir şeye işaret etmeye başlar; bu boş bir listedir. İlklendirmek, ona eklemekle aynı şeydir. Örneğin:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
Not: İşinizfree(array); bittiğinde bunu unutmayın!