Diziden ptr'ye doğal tür bozunumuyla C'de standart dizi kullanımı
@Bo Persson doğru onun büyük cevap devletler burada :
Bir diziyi parametre olarak iletirken, bu
void arraytest(int a[])
tam olarak aynı anlama gelir
void arraytest(int *a)
Bununla birlikte, yukarıdaki iki formun da şunu ekleyeyim:
tam olarak aynı demek
void arraytest(int a[0])
bu tamamen aynı anlamına gelir
void arraytest(int a[1])
bu tamamen aynı anlamına gelir
void arraytest(int a[2])
bu tamamen aynı anlamına gelir
void arraytest(int a[1000])
vb.
Yukarıdaki dizi örneklerinin her birinde, girdi parametresi türü bir değerine düşerint *
ve derleme seçenekleri -Wall -Wextra -Werror
açık olsa bile hiçbir uyarı ve hata olmadan çağrılabilir ( bu 3 derleme seçeneğiyle ilgili ayrıntılar için burada depomuza bakın ) bu:
int array1[2];
int * array2 = array1;
arraytest(array1);
arraytest(array2);
Nitekim olarak, "boyut" değeri ( [0]
, [1]
, [2]
, [1000]
dizi parametrenin içine, vs.) burada estetik / öz dokümantasyon amaçlı görünüşe bakılırsa, ve herhangi bir pozitif tam sayı olabilir ( size_t
istediğiniz sanırım tip)!
Bununla birlikte, pratikte, işlevin almasını beklediğiniz dizinin minimum boyutunu belirtmek için kullanmalısınız, böylece kod yazarken izlemeniz ve doğrulamanız kolay olur. MISRA-C-2012 standardı ( al / burada £ 15.00 için standart 236-pg 2012-sürüm PDF bugüne kadar devlet (vurgu eklenmiştir) olarak geçer):
Kural 17.5 Bir dizi türüne sahip olduğu bildirilen bir parametreye karşılık gelen işlev bağımsız değişkeni, uygun sayıda elemana sahip olmalıdır.
...
Bir parametre belirtilen boyuta sahip bir dizi olarak bildirilirse, her işlev çağrısındaki karşılık gelen bağımsız değişken, en az dizi kadar öğeye sahip bir nesneyi işaret etmelidir.
...
Bir işlev parametresi için bir dizi tanımlayıcının kullanılması, işlev arabirimini bir işaretçi kullanmaktan daha açık bir şekilde belirtir. İşlev tarafından beklenen minimum eleman sayısı açıkça belirtilmiştir, ancak bu bir işaretçi ile mümkün değildir.
Başka bir deyişle, C standardı teknik olarak onu zorlamasa da, açık boyut biçimini kullanmanızı önerirler - en azından bir geliştirici olarak size ve kodu kullanan diğerlerine, işlevin hangi boyut dizisini beklediğini netleştirmeye yardımcı olur. geçmek için.
C'deki dizilerde tür güvenliğini zorlama
@Winger Sendon'un cevabımın altındaki bir yorumda işaret ettiği gibi, C'yi bir dizi tipini dizi boyutuna bağlı olarak farklı şekilde ele almaya zorlayabiliriz !
Öncelikle, kullandığınız, sadece yukarıda benim örnekte tanımak gerekir int array1[2];
böyle: arraytest(array1);
nedenleri array1
otomatik çürüme bir içine int *
. ANCAK, yerine adresini alıp ararsanız , tamamen farklı bir davranışla karşılaşırsınız! array1
arraytest(&array1)
Şimdi, bir int *
! Bunun yerine, &array1
is türü, "boyut 2 int dizisine işaretçi " veya " int türünde boyut 2 dizisine işaretçi"int (*)[2]
anlamına gelir . Bu nedenle, bir dizide tür güvenliğini kontrol etmek için C'yi şu şekilde yapabilirsiniz:
void arraytest(int (*a)[2])
{
}
Bu sözdiziminin okunması zordur, ancak bir işlev göstericisininkine benzer . Çevrimiçi araç, cdecl , bize şunu söyler int (*a)[2]
: "int dizisinin 2. dizisine işaretçi olarak bir işaretçi bildir " (2 int
s dizisine işaretçi ). : Parantez olmadığı versiyon ile karıştırmayın Do NOT int * a[2]
, araçlar: "int pointer dizisi 2. olarak bir beyan" (2 dizisi işaretçiler için int
).
Şimdi, bu işlev, bunu adres işleci ( &
) ile bu şekilde çağırmanızı GEREKTİRİR , bir girdi parametresi olarak DOĞRU BOYUTLU BİR DİZAYA İŞARETLEYİCİ !:
int array1[2];
arraytest(&array1);
Ancak bu, bir uyarı oluşturacaktır:
int array1[2];
arraytest(array1);
Bu kodu burada test edebilirsiniz .
C derleyicisini bu uyarıyı bir hataya dönüştürmeye zorlamak için, her zaman arraytest(&array1);
yalnızca doğru boyut ve türde ( int array1[2];
bu durumda) bir giriş dizisi kullanarak çağırmanız GEREKİR -Werror
, derleme seçeneklerinize ekleyin . Yukarıdaki test kodunu onlinegdb.com'da çalıştırıyorsanız, bunu sağ üstteki dişli çark simgesini tıklayarak yapın ve bu seçeneği yazmak için "Ekstra Derleyici Bayrakları" na tıklayın. Şimdi, bu uyarı:
main.c:34:15: warning: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Wincompatible-pointer-types]
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
bu yapı hatasına dönüşecek:
main.c: In function ‘main’:
main.c:34:15: error: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Werror=incompatible-pointer-types]
arraytest(array1);
^~~~~~
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
void arraytest(int (*a)[2])
^~~~~~~~~
cc1: all warnings being treated as errors
Ayrıca, belirli bir boyuttaki diziler için "güvenli tür" işaretçileri oluşturabileceğinizi unutmayın, örneğin:
int array[2];
int (*array_p)[2] = &array;
... ama yok illa bana C ++ dil sözdizimi karmaşıklığı, ayrıntı ve zorluk architecting kod olağanüstü yüksek maliyetle, her yerde kuvvet tip güvenliği için kullanılan antikalar çok hatırlatıyor olarak, bu tavsiye ve hangi ben sevmediğim ve daha önce defalarca mırıldandı (örn: burada "C ++ Üzerine Düşüncelerim" konusuna bakın ).
Ek testler ve deneyler için, hemen aşağıdaki bağlantıya da bakın.
Referanslar
Yukarıdaki bağlantılara bakın. Ayrıca:
- Çevrimiçi kod denemem: https://onlinegdb.com/B1RsrBDFD