Bu deyim doğal olarak 1B dizi tahsisinin dışında kalır. Bazı rasgele türden bir 1B dizisi ayırarak başlayalım T
:
T *p = malloc( sizeof *p * N );
Basit, değil mi? İfadesi *p
türü vardır T
, böylece, sizeof *p
aynı sonucu verir sizeof (T)
bu yüzden bir için yeterli alan tahsis ediyoruz, N
bir -eleman dizisi T
. Bu her türT
için geçerlidir .
Şimdi, T
gibi bir dizi türü ile değiştirelim R [10]
. Daha sonra tahsisatımız
R (*p)[10] = malloc( sizeof *p * N);
Buradaki anlambilim 1D tahsis yöntemiyle tamamen aynıdır ; tüm değişen türü p
. Bunun yerine T *
şimdi R (*)[10]
. İfade *p
, type T
olan türe sahiptir R [10]
, bu sizeof *p
nedenle eşdeğer sizeof (T)
olan ile eşdeğerdir sizeof (R [10])
. Dolayısıyla N
, 10
öğeye göre bir dizi için yeterli alan ayırıyoruz:R
.
İstersek bunu daha da ileri götürebiliriz; varsayalım R
kendisi bir dizi türüdür int [5]
. Bunun yerine koy R
ve biz
int (*p)[10][5] = malloc( sizeof *p * N);
Aynı anlaşma - sizeof *p
aynıdır sizeof (int [10][5])
ve biz tutmak için bellek yeterince büyük bitişik bir yığın tahsis kadar rüzgar N
tarafından 10
tarafından 5
dizisiint
.
Yani bu tahsis tarafı; erişim tarafı ne olacak?
Alt []
simge işleminin işaretçi aritmetiği açısından tanımlandığını unutmayın : 1a[i]
olarak tanımlanır . Böylece, alt simge operatörü dolaylı olarak bir göstericiye referansta bulunur. Eğer bir göstericidir açıkça tekli ile kaldırma tarafından sivri-değerin ya erişebileceğiniz operatörü:*(a + i)
[]
p
T
*
T x = *p;
veya[]
alt simge operatörünü kullanarak :
T x = p[0]; // identical to *p
Böylece, p
bir dizinin ilk öğesini işaret ediyorsa , işaretçi üzerinde bir alt simge kullanarak bu dizinin herhangi bir öğesine erişebilirsiniz p
:
T arr[N];
T *p = arr; // expression arr "decays" from type T [N] to T *
...
T x = p[i]; // access the i'th element of arr through pointer p
Şimdi ikame işlemimizi tekrar yapalım T
ve dizi tipiyle değiştirelim R [10]
:
R arr[N][10];
R (*p)[10] = arr; // expression arr "decays" from type R [N][10] to R (*)[10]
...
R x = (*p)[i];
Hemen görünen bir fark; p
alt simge operatörünü uygulamadan önce açıkça başvuruyu kaldırıyoruz . Alt simge yapmak istemiyoruz p
, neyin p
işaret ettiğini (bu durumda dizi arr[0]
) belirtmek istiyoruz . Tekli yana *
simge daha düşük önceliğe sahiptir []
operatörü, biz açıkça gruba parantez kullanmak zorunda p
olan *
. Ancak yukarıdan bunun *p
aynısı olduğunu unutmayın p[0]
, böylece onu yerine koyabiliriz
R x = (p[0])[i];
ya da sadece
R x = p[0][i];
Böylece, p
2B bir diziyi gösteriyorsa, bu diziyi şu şekilde indeksleyebiliriz p
:
R x = p[i][j]; // access the i'th element of arr through pointer p;
// each arr[i] is a 10-element array of R
Bunu yukarıdaki ile aynı sonuca götürmek ve aşağıdakilerle ikame R
etmek int [5]
:
int arr[N][10][5];
int (*p)[10][5]; // expression arr "decays" from type int [N][5][10] to int (*)[10][5]
...
int x = p[i][j][k];
Bu işler sadece aynı ise p
noktalar düzenli diziye yoksa belleğe işaret eğer yoluyla ayrılanmalloc
.
Bu deyimin aşağıdaki faydaları vardır:
- Basit - parça parça ayırma yönteminin aksine yalnızca bir satır kod
T **arr = malloc( sizeof *arr * N );
if ( arr )
{
for ( size_t i = 0; i < N; i++ )
{
arr[i] = malloc( sizeof *arr[i] * M );
}
}
- Tahsis edilen dizinin tüm satırları * bitişiktir *, bu yukarıdaki parçalı ayırma yönteminde geçerli değildir;
- Dizinin serbest bırakılması, tek bir çağrı ile aynı derecede kolaydır
free
. Yine, arr[i]
ayrılmadan önce her birini serbest bırakmanız gereken parçalı tahsis yöntemi için doğru değildir arr
.
Bazen parçalı ayırma yöntemi tercih edilir, örneğin yığınınız kötü bir şekilde parçalanmışsa ve belleğinizi bitişik bir yığın olarak ayıramazsanız veya her satırın farklı bir uzunluğa sahip olabileceği "pürüzlü" bir dizi ayırmak istediğinizde. Ancak genel olarak, gitmenin daha iyi yolu budur.
1. Dizilerin işaretçi olmadığını unutmayın - bunun yerine, dizi ifadeleri gerektiği gibi işaretçi ifadelerine dönüştürülür.