Dizileri fonksiyonlara gecirmek
DİZİLERİ FONKSİYONLARA GEÇİRMEK
Bir dizi argümanını fonksiyona geçirebilmek için, dizinin ismini parantez kullanmadan belirtmeliyiz. Örneğin, eğer saatliksicaklik dizisi
1 |
int saatliksicaklik [24];
|
olarak bildirilmişse
1 |
diziyiayarla ( saatliksicaklik,24);
|
fonksiyon çağrısı, saatliksicaklik dizisini ve boyutunu diziyiayarla fonksiyonuna geçirir. Bir diziyi fonksiyona geçirirken, fonksiyonun dizinin belirli sayıdaki elemanını işleyebilmesi için, dizinin boyutu da geçirilir.
C, dizileri fonksiyonlara otomatik olarak referansa göre çağırma yöntemiyle geçirir ; çağrılan fonksiyonlar, çağırıcının orijinal dizilerindeki elemanların değerlerini değiştirebilir. Dizinin ismi, gerçekte dizinin ilk elemanının adresidir! Dizinin başlangıç adresi geçirildiğinden, çağrılan fonksiyon dizinin nerede tutulduğunu kesin olarak bilir. Bu sebepten, çağrılan fonksiyon, fonksiyon gövdesinde dizinin elemanlarını değiştirirken gerçek dizinin elemanlarını orijinal hafıza konumlarında değiştirmektedir.
Şekil 6.12, dizi isminin gerçektende dizinin ilk elemanının başlangıç adresini olduğunu %p dönüşüm belirteci kullanarak ve dizi, &dizi[0] ve &dizi değerlerini yazdırarak göstermektedir. %p dönüşüm belirteci, adresleri yazdırmak için kullanılan özel bir belirteçtir. %p dönüşüm belirteci genellikle adresleri onaltılık sistemde yazdırır. Onaltılık sistemlerde (heksadecimal) sayılar, 0'dan 9'a kadar rakamları ve A'dan F'ye kadar harfleri içermektedir. Bunlar, genellikle çok büyük tamsayıları kısaltarak gösterebilmek için kullanılırlar. Ekler E ikilik ( binary ), sekizlik ( octal ) ve onaltılık ( heksadecimal ) sayı sistemleri arasındaki ilişkiyi göstermektedir. Çıktı, dizi ve &dizi[0] için aynı değeri (bu örnekte 0065FDF0) göstermektedir. Bu programın çıktısı her sistemde farklı olabilir ancak adresler her zaman özdeş çıkacaktır.
Performans İpuçları 6.4
Dizileri referansa göre çağırma, performans açısından oldukça mantıklıdır. Eğer diziler değere göre çağırma ile geçirilmiş olsaydı, her elemanının kopyası geçirilecekti. Büyük ve sıklıkla çağrılan dizilerde bu oldukça fazla vakit alacaktı ve fazladan hafızaya ihtiyaç duyacaktı.
Yazılım Mühendisliği Gözlemleri 6.2
10.Ünitede açıklayacağımız basit bir numarayla dizileri değere göre geçirmek mümkün olabilir.
Dizinin tümü referansa göre geçirilse de dizinin bağımsız elemanları basit değişkenlerde olduğu gibi değere göre çağrılarla geçirilirler. Bu tarzda basit ve tek veri parçalarına skaler nicelikler denir. Bir dizinin elemanını fonksiyona geçirmek için, dizinin ismini ve elemanın dizideki belirtecini fonksiyon çağrısında argüman olarak kullanmak gerekir. 7.Ünitede, skaler nicelikler için (bağımsız değişken ve dizi elemanları gibi) referansa göre çağrıların nasıl yapılacağını göstereceğiz.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* Şekil 6.12: fig06_12.c Bir dizinin ismi &dizi[ 0 ] ile aynıdır. */ #include <stdio.h> int main( ) { char dizi[ 5 ]; printf( " dizi = %p\n &dizi[0] = %p\n" " &dizi= %p\n", dizi, &dizi[ 0 ], &dizi); return 0; } |
Dizi = 0065FDF0
&dizi[0] = 0065FDF0
&dizi = 0065FDF0
Şekil 6.12 Dizinin ismi ile dizinin ilk elemanının adresi aynıdır.
Bir fonksiyonun, fonksiyon çağrısı esnasında diziyi alabilmesi için, fonksiyonun parametre listesinin alınacak diziyi belirlemesi gerekir. Örneğin, diziyiayarla fonksiyonunun başlığı
void diziyiayarla(int b[ ] , int boyut)
biçiminde yazılabilir. Böylece, diziyiayarla fonksiyonunun b parametresinde tamsayılardan oluşan bir dizi ve boyut parametresinde de dizi elemanlarının sayısını almayı beklediği belirtilir. Dizinin büyüklüğünü köşeli parantezler içine yazmaya gerek yoktur. Eğer yazılırsa, derleyici bu sayının sıfırdan büyük olup olmadığını kontrol eder ve daha sonra da ihmal eder. Negatif bir büyüklük belirtmek hata oluşmasına sebep olur. Diziler otomatik olarak referansa göre geçirildiklerinden, çağrılan fonksiyon dizi ismi olarak b kullandığında aslında çağırıcıdaki diziyi belirtmektedir (az önceki çağrıda saatliksicaklik). 7.ünitede, fonksiyonun bir dizi aldığını belirten farklı gösterimler de tanıtacağız. İleride göreceğimiz gibi, bu gösterimler C'de dizi ve göstericiler arasındaki yakın ilişkiye dayanmaktadır.
diziyiayarla fonksiyonunun garip görünen prototipini inceleyelim:
1 |
void diziyiayarla( int [ ] , int );
|
Bu prototip
void diziyiayarla ( int herhangiBirDiziIsmi [ ] , int herhangiBirDegisken);
biçiminde olabilirdi. Ancak 5.ünitede öğrendiğimiz gibi, C derleyicisi prototipler içindeki değişken isimlerini ihmal eder.
İyi Programlama Alıştırmaları 6.6
Bazı programcılar programı daha açık hale getirmek için, fonksiyon prototipinde değişken isimleri kullanırlar.Derleyici bunları ihmal eder.
Prototipin, derleyiciye argüman sayısını ve her argümanının tipini ( argümanların çalıştırılacakları sırada ) söylediğini hatırlayınız.
Şekil 6.13, tüm diziyi geçirmekle, yalnızca bir dizi elemanı geçirmek arasındaki farkı göstermektedir. Program, tamsayı dizisi a'nın ilk 5 elemanını yazdırmaktadır. ( 17 ve 18.satır) Daha sonra a dizisi ve dizinin boyutu, a'nın elemanlarının her birinin 2 ile çarpıldığı, diziyiAyarla fonksiyonuna (34.satırda tanımlanmıştır) geçirilmiştir. Şimdi program a[3]'ün değerini yazdırmakta ve a[3]'ü elemaniAyarla fonksiyonuna (42.satırda tanımlanmıştır) geçirmektedir. elemaniAyarla fonksiyonu, argümanını 2 ile çarpmakta ve yeni değerini yazdırmaktadır. a[3] , main içinde yeniden yazdırıldığında a[3]'ün değiştirilmediğini çünkü bağımsız dizi elemanlarının değere göre çağırma ile geçirildiğine dikkat ediniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
/* Şekil 6.13: fig06_13.c Dizileri ve dizi elemanlarını fonksiyonlara geçirme */ #include <stdio.h> #define BOYUT 5 void diziyiAyarla( int [], int ); /* garip gözükür */ void elemaniAyarla( int ); int main( ) { int a[ BOYUT ] = { 0, 1, 2, 3, 4 }, i; printf( "Bütün dizinin referansa göre çağrılarak geçmesinin " "etkileri:\n\nOrijinal dizinin " "değerleri:\n" ); for ( i = 0; i <= BOYUT - 1; i++ ) printf( "%3d", a[ i ] ); printf( "\n" ); diziyiAyarla ( a, BOYUT); /*referansa göre çağrılarak geçti*/ printf( "Ayarlanan dizinin değerleri:\n" ); for ( i = 0; i <= BOYUT - 1; i++ ) printf( "%3d", a[ i ] ); printf( "\n\n\nDizi elemanının değere göre çağrılarak " "geçmesinin etkileri:\n\na[3] değeri %d\n", a[ 3 ] ); elemaniAyarla ( a[ 3 ] ); printf( "a[ 3 ] değeri %d\n", a[ 3 ] ); return 0; } void diziyiAyarla ( int b[], int boyut) { int j; for ( j = 0; j <= boyut - 1; j++ ) b[ j ] *= 2; } void elemaniAyarla ( int e ) { printf( "elemaniAyarla da ki değer %d\n", e *= 2 ); } |
Bütün dizinin referansa göre çağrılarak geçmesinin etkileri
Orijinal dizinin değerleri:
0 1 2 3 4
Ayarlanan dizinin değerleri:
0 2 4 6 8
Dizi elemanının değere göre çağrılarak geçmesinin etkileri:
a[3] değeri 6
elemaniAyarla da ki değer 12
a[3] değeri 6
Şekil 6.13 Dizileri ve dizi elemanlarını fonksiyonlara geçirme
Programlarınızda, fonksiyonun diziyi değiştirmemesi gereken bazı durumlar olabilir. Diziler referansa göre çağırma ile geçirildiğinden, bir dizideki değerlerin değiştirilmesini kontrol etmek güçtür. C, const tip belirteciyle bir fonksiyon içinde dizinin elemanlarının değerlerinin değiştirilmesini engeller. Bir dizi parametresinden önce const kullanılırsa, dizi elemanları fonksiyon gövdesi içinde sabit hale gelir ve fonksiyon gövdesinde dizinin elemanlarını değiştirmeye çalışmak, derleme anında hataya yol açar. Bu, programcıya, programını diziyi değiştirmeyecek biçimde düzeltme imkanı verir. const belirteci, ANSI standardında açıkça belirlenmiş olsa da C sistemlerinin bunu uygulama yetenekleri değişebilir.
Şekil 6.14, const belirtecinin kullanımını göstermektedir. diziyiAyarlamayiDene fonksiyonu (16.satır), const int b[ ] parametresiyle tanımlanarak b dizisi sabit ve değiştirilemez hale getirilmiştir. Programın çıktısı, derleyicinin hata mesajlarını göstermektedir. Hatalar sizin sisteminizde farklı olabilir. Fonksiyonun, dizi elemanlarını değiştirmek için yaptığı üç deneme de derleyici hatasıyla karşılaşmıştır. const belirteci 7.ünitede yeniden tartışılacaktır.
Yazılım Mühendisliği Gözlemleri 6.3
const tip belirteci, fonksiyon tanımında parametrelere uygulanarak, orijinal dizinin fonksiyon gövdesi içinde değiştirilmesi engellenebilir. Bu, en az yetki prensibinin başka bir örneğidir. Fonksiyonlara, gerçekten gerekmedikçe diziyi değiştirme yeteneği verilmemelidir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* Şekil 6.14: fig06_14.c const tip belirtecinin dizilerde kullanımı */ #include <stdio.h> void diziyiAyarlamayiDene ( const int [] ); int main( ) { int a[] = { 10, 20, 30 }; diziyiAyarlamayiDene ( a ); printf("%d %d %d\n", a[ 0 ], a[ 1 ], a[ 2 ] ); return 0; } void diziyiAyarlamayiDene ( const int b[] ) { b[ 0 ] /= 2; /* hata */ b[ 1 ] /= 2; /* hata */ b[ 2 ] /= 2; /* hata */ } |
Compiling...
Fig06_14.c(18) :error C2166: l-value specifies const object
Fig06_14.c(19) :error C2166: l-value specifies const object
Fig06_14.c(20) :error C2166: l-value specifies const object
Şekil 6.14 const tip belirtecinin kullanımı
Bilinmesi Gerekli
Arduino

Arduino ile bilgisayar programlarınızı gerçek dünyaya taşıyabilirsiniz.
İlk Transistör

Bell laboratuvarlarında icat edilen ilk transistör







