Dizi öğelerine [] operatörü yerine işaretçi aritmetiği üzerinden başvurmak kötü mü?


12

C programlamayı öğrenmeye başladım ve işaretçiler ve diziler hakkındaki anlayışımı geliştirmek için, herhangi bir işaretçi oluşturmadan bir dizinin öğelerine başvurmaya çalıştım:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

Kodun tamamı derlenir ve kusursuz çalışır.

Ben büyük bir kaynak kodunda her dizi için bir işaretçi oluşturmak zorunda hayal çok verimsiz gibi görünüyor.

Bu nedenle, bir işaretçi kullanılarak bir dizinin adresinin depolanması ve alınması yerine, yukarıda gösterildiği gibi dizinin adresini doğrudan kullanmak kötü bir programlama uygulaması mıdır?


Kullanmak printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));işaretçi aritmik önlemek ve anlamak daha kolaydır.
Kasper van den Berg

1
Haha, beni yakaladın. Bunu sadece işaretçilerin ve dizilerin nasıl çalıştığını daha iyi anlamak için bir deney olarak yaptım.
Niko Gambt

İşaretçi aritmetiği aslında dizi indekslerini kullanmaktan yaklaşık% 30 daha hızlıdır.
Andy

Yanıtlar:


16

Sadece daha az okunabilir ölçüde "kötü". a[x]ile aynı şeydir *(a+x), bu nedenle verimlilik veya davranışta hiçbir fark yoktur (aslında x[a]da işe yarayacaktır). Bu sadece insanlar a[x]için genellikle çok daha sezgiseldir.

Ancak bu okunabilirliğin önemli olmadığı anlamına gelmez. Ne kadar büyük olduğunu görmek için, kodda görürseniz bu iki ifadeyi nasıl "okuyacağınızı" düşünün:

  • *(a+x)= "İşaretçi ave tamsayı toplamının işaret ettiği şey x"
  • a[x]= "Dizinin xth üyesi a"

Benzer şekilde, bir dizi öğesinin adresine başvurmanız gerektiğinde:

  • (a+x)= "İşaretçi ave tamsayı toplamı x"
  • &a[x]= "Dizinin xth üyesinin üyesi a"

Çoğu zaman, []birkaç farklı dizide (özellikle dizilerin dizileri) çalışan önemsiz bir koda baktığınızda sürümleri anlamak daha kolaydır. Bu yüzden []operatör ilk etapta var olur.

PS: Bu tür şeyleri kesinlikle bir öğrenme egzersizi olarak yapmak çok iyi bir fikirdir. Dizilerin gerçekten sadece işaretçiler ve ofsetler olduğunu anlamak önemlidir.


Bu. Teşekkür ederim. Ben sadece gerçekten bilmek istiyorum ne olduğunu derin fark ettim, herhangi bir dizi elemanının adresine başvurmak ve daha sonra başka bir elemanın adresine bakın ve sonra başka, hala kötü mü Bir işaretçi kullanmak DEĞİLDİR, bunun yerine, diziyi doğrudan yaptığım gibi kullanın? Bu meselemi noktaya koymak gerçekten zor oldu, bu yüzden OP'ye yazmadım. Her neyse, sormadım, cevabınız tatmin edici.
Niko Gambt

1
@NikoGambt Her zaman başka bir soru sorabilirsiniz =)
Ixrec

1
Sadece ne ölçüde ... demek istiyorsun ? Programlama dillerinin tüm amacı, kodun insanların okumasını kolaylaştırmaktır. Bunu önemsemeseydik, hepimiz onaltılı olarak op kodları yazardık.
Solomon Yavaş

2
Diziler işaretçi değildir, dolaylı olarak işaretçilerin çürümesi.
CodesInChaos

4

Evet, bu kötü bir uygulamadır, ancak verimsizlik nedeniyle değil.

Dizi operatörü kaputun altında işaretçi aritmetiği kullanır, bu nedenle eşit derecede verimlidir.

İşaretçi aritmetrisi ile ilgili sorun çok hataya yatkın ve okunması daha zor olmasıdır.

Temel kural: Zorunlu olmadıkça işaretçi aritmetiği kullanmayın.


1
Zaten işaretçi aritmetiği kullandığından, bu işaretçiler de aynı derecede hataya açık ve okunması zor değil mi?
Niko Gambt

1
@NikoGambt derleyicileri kaputun altında işaretçi aritmik yapmakta oldukça iyidir ve nadiren 'hatalar' yapar; sonuç olarak kötü hatalarla hata yapacak programcılar.
Kasper van den Berg

@KaspervandenBerg Evet, katılıyorum. Ancak, programcılar tarafından yapılan hatalarla ilgileniyorum ve bir dizinin adresine başvurmak gerektiğinde, yukarıda yaptığım şeyi yapmanın kötü bir programlama uygulaması olup olmadığından emin değilim. , bu gibi durumlar varsa.
Niko Gambt

1
@NikoGambt Performans amaçları için daha az okunabilir bir şey yazmak neredeyse her zaman kötü bir uygulamadır, ancak kazanç için daha az okunabilir bir şey yazmak kesinlikle kötü bir uygulamadır.
Neil

@Neil Küçük denemem anlamsız değil. Bunu yaparak, derleyicinin çok boyutlu bir diziye başvurmak için bir dizi işaretçi oluşturduğunu öğrendim. Ancak, okunabilirliğin performanstan daha önemli olduğunu söylediğiniz için, sanırım bu hala kötü bir programlama uygulamasıdır.
Niko Gambt

0

Öğreniminizi c serinletin, c küçük dil bükümlerinden birini keşfettiniz. Bir dizide işaretçi aritmetiği değil, bir işaretçi dizisi yapıyorsunuz. Dizilerde işaretçi aritmetiği yapmak mümkün değildir. Bir dizi bir işaretçiye bozulur, ancak kendi kendine işaret eden bir işaretçi değildir. Sahip olduğum şey (cmaster'ın yorumuna bakın)

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

Bu işaretçinin kaydı silindiğinde, yalnızca hesapladığınız işaretçinin işaret ettiği değer verilir. Genelde yaptığınız şeyi yapmanın bir anlamı yoktur. Ancak diziyi doğrusallaştırıp daha sonra bu şekilde bir adım atabilirsiniz.

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

Adım onu ​​x_dim. Umarım cevabım netleşir!


OP'den bir int* array[ROW];an int array[ROW][COLUMN];veya bir an kullanıp kullanmadığı açık değildir int (*array)[COLUMN];. Bu üç tanımdan her ikisi de OP'deki kodla kullanılabilir.
cmaster - eski haline monica

evet bunun farkındayım, cevabım bu noktada biraz sakar. Düzeltiyorum, teşekkürler!
fhtuft
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.