Henüz C öğrenirken, önce sıradan şeyler yerine diziler ve işaretçiler arasındaki farkları gerçekten anlamaya çalışmanızı tavsiye ederim .
Parametreler ve diziler alanında, devam etmeden önce açık olması gereken birkaç kafa karıştırıcı kural vardır. İlk olarak, bir parametre listesinde bildirdiğiniz şey özel olarak ele alınır. C'de işlev parametresi olarak şeylerin anlamsız olduğu durumlar vardır. Bunlar şunlardır:
- Parametre olarak işlevler
- Parametre olarak diziler
Parametre olarak diziler
İkincisi belki hemen belli değil. Ancak, bir dizi boyutunun boyutunun C'deki türün bir parçası olduğunu (ve boyut boyutu verilmeyen bir dizinin eksik bir türü olduğunu) düşündüğünüzde netleşir. Öyleyse, diziyi değerine göre alan (bir kopya alan) bir işlev oluşturacaksanız, bunu yalnızca bir boyut için yapabilir! Ek olarak, diziler büyüyebilir ve C olabildiğince hızlı olmaya çalışır.
C'de, bu nedenlerden dolayı, dizi değerleri mevcut değildir. Bir dizinin değerini almak istiyorsanız, onun yerine elde ettiğiniz şey, o dizinin ilk elemanına bir göstericidir. Ve aslında zaten çözüm burada yatıyor. Bunun yerine, bir dizi parametre çizim-ön geçersiz, bir Cı-derleyici dönüşümü , ilgili parametresinin türü bir işaretçi olduğu. Bunu unutma, bu çok önemli. Parametre bir dizi olmayacak, bunun yerine ilgili öğe türüne bir gösterici olacaktır.
Şimdi, bir dizi geçirmeye çalışırsanız, bunun yerine iletilen şey dizilerin ilk elemanına bir göstericidir.
Gezi: Parametre olarak işlevler
Tamamlanması için ve bunun konuyu daha iyi anlamanıza yardımcı olacağını düşündüğüm için, parametre olarak bir işleve sahip olmaya çalıştığınızda durumun ne olduğuna bakalım. Aslında, ilk önce hiçbir anlam ifade etmeyecektir. Bir parametre nasıl bir işlev olabilir? Huh, o yerde elbette bir değişken istiyoruz! Ne bu olduğunda derleyici yapmasıdır Yani, yine, hiç dönüşümü bir içine işlev işlev işaretçisi . Bir işlevi iletmeye çalışmak, bunun yerine ilgili işleve bir işaretçi iletecektir. Dolayısıyla, aşağıdakiler aynıdır (dizi örneğine benzer):
void f(void g(void));
void f(void (*g)(void));
Parantezlerin *g
gerekli olduğunu unutmayın . Aksi takdirde, dönen bir işleve void*
bir işaretçi yerine geri dönen bir işlevi belirtirdi void
.
Dizilere dön
Şimdi, başlangıçta dizilerin eksik bir türe sahip olabileceğini söyledim - bu, henüz bir boyut vermezseniz olur. Bir dizi parametresinin olmadığını, bunun yerine herhangi bir dizi parametresinin bir işaretçi olduğunu zaten anladığımız için, dizinin boyutunun önemi yoktur. Bu, derleyicinin aşağıdakilerin tümünü çevireceği ve hepsi aynı şey olduğu anlamına gelir:
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
Elbette, içine herhangi bir boyut koyabilmek pek mantıklı değil ve sadece atılıyor. Bu nedenle, C99 bu sayılar için yeni bir anlam buldu ve parantezler arasında başka şeylerin görünmesine izin verdi:
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
Son iki satır, işlev içinde "argv" yi değiştiremeyeceğinizi söylüyor - bu bir const işaretçisi haline geldi. Yine de yalnızca birkaç C derleyicisi bu C99 özelliklerini destekler. Ancak bu özellikler, "dizi" nin aslında bir olmadığını açıkça ortaya koyuyor. Bu bir işaretçi.
Uyarı kelimesi
Yukarıda söylediğim her şeyin yalnızca bir işlevin parametresi olarak bir diziye sahip olduğunuzda doğru olduğuna dikkat edin . Yerel dizilerle çalışıyorsanız, dizi bir işaretçi olmayacaktır. Bu olacak davranmaya değeri okunduğunda gibi bir işaretçi önceki bir dizi dönüştürülecektir açıkladı çünkü bir işaretçi olarak. Ancak işaretçilerle karıştırılmamalıdır.
Klasik bir örnek şudur:
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;