Gönderinizde söyledikleriniz kesinlikle doğrudur. Her C geliştiricisinin, C dili ile belirli bir yeterlilik seviyesine ulaştıklarında (eğer) tam olarak aynı keşfi ve aynı sonuca ulaştığını söyleyebilirim.
Uygulama alanınızın özellikleri, belirli bir sabit boyutta bir dizi gerektirdiğinde (dizi boyutu bir derleme zamanı sabitidir), böyle bir diziyi bir işleve geçirmenin tek uygun yolu, diziye işaretçi parametresi kullanmaktır.
void foo(char (*p)[10]);
(C ++ dilinde bu, referanslarla da yapılır
void foo(char (&p)[10]);
).
Bu, tam olarak doğru boyuttaki dizinin bağımsız değişken olarak sağlandığından emin olan dil düzeyinde tür denetimini etkinleştirir. Aslında, birçok durumda insanlar farkında bile olmadan bu tekniği örtük olarak kullanır ve dizi türünü typedef adının arkasına gizler.
typedef int Vector3d[3];
void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);
Ek olarak, yukarıdaki kodun Vector3d
bir dizi veya bir türle ilişkili olarak değişmediğini unutmayın struct
. Vector3d
Herhangi bir zamanda tanımını bir diziden a struct
ve geri olarak değiştirebilirsiniz ve işlev bildirimini değiştirmek zorunda kalmazsınız. Her iki durumda da işlevler "referans olarak" bir toplu nesne alacaklardır (bunun istisnaları vardır, ancak bu tartışma bağlamında bu doğrudur).
Bununla birlikte, bu dizi geçirme yönteminin açıkça çok sık kullanıldığını görmeyeceksiniz, çünkü çok fazla insan oldukça karmaşık bir sözdizimiyle kafasını karıştırıyor ve C dilinin bu tür özellikleriyle onları doğru şekilde kullanmak için yeterince rahat değil. Bu nedenle, ortalama gerçek hayatta bir diziyi ilk öğesine işaretçi olarak geçirmek daha popüler bir yaklaşımdır. Sadece "daha basit" görünüyor.
Ancak gerçekte, dizi geçişi için ilk öğeye göstericiyi kullanmak çok niş bir tekniktir, çok özel bir amaca hizmet eden bir hile: Tek ve tek amacı, farklı boyuttaki dizileri (yani çalışma zamanı boyutu) geçirmeyi kolaylaştırmaktır. . Gerçekten çalışma zamanı boyutundaki dizileri işleyebilmeniz gerekiyorsa, bu tür bir diziyi geçirmenin uygun yolu, ek bir parametre tarafından sağlanan somut boyutla ilk öğesine bir göstericidir.
void foo(char p[], unsigned plen);
Aslında, birçok durumda, çalışma zamanı boyutundaki dizileri işleyebilmek çok yararlıdır ve bu da yöntemin popülerliğine katkıda bulunur. Birçok C geliştiricisi, sabit boyutlu bir diziyi işleme ihtiyacıyla asla karşılaşmaz (veya asla fark etmez), böylece uygun sabit boyutlu tekniğe aldırış etmez.
Bununla birlikte, dizi boyutu sabitse, onu bir elemana işaretçi olarak geçirme
void foo(char p[])
maalesef günümüzde oldukça yaygın olan teknik düzeyinde büyük bir hatadır. Diziye işaretçi tekniği bu gibi durumlarda çok daha iyi bir yaklaşımdır.
Sabit boyutlu dizi geçirme tekniğinin benimsenmesini engelleyebilecek bir başka neden, dinamik olarak tahsis edilmiş dizilerin tiplendirilmesine yönelik naif yaklaşımın baskınlığıdır. Örneğin, program sabit tür dizileri çağırırsa char[10]
(örneğinizde olduğu gibi), ortalama bir geliştirici şu malloc
dizileri verecektir:
char *p = malloc(10 * sizeof *p);
Bu dizi şu şekilde bildirilen bir işleve geçirilemez:
void foo(char (*p)[10]);
Bu, ortalama geliştiricinin kafasını karıştırır ve onları daha fazla düşünmeden sabit boyutlu parametre bildiriminden vazgeçirir. Gerçekte ise sorunun kökü saf malloc
yaklaşımda yatmaktadır . malloc
Yukarıda gösterilen çalıştırma büyüklüğü diziler için ayrılmalıdır. Dizi türünün derleme zamanı boyutu varsa, bunun daha iyi bir yolu malloc
aşağıdaki gibi görünür
char (*p)[10] = malloc(sizeof *p);
Bu, elbette, yukarıda beyan edilenlere kolayca aktarılabilir foo
foo(p);
ve derleyici uygun tip kontrolünü gerçekleştirecektir. Ancak yine, hazırlıksız bir C geliştiricisi için bu aşırı derecede kafa karıştırıcıdır, bu yüzden onu "tipik" ortalama günlük kodda çok sık göremezsiniz.
10
olması gerekmez, kapsamdaki herhangi bir değişkenle değiştirilebilir