Örneklerle C Programlamada Fonksiyon İşaretçileri

İçindekiler:

Anonim

İşaretçiler, tek bir değer döndürmek için sınırlı olduğumuz 'C' işlevlerine büyük olasılıklar verir. İşaretçi parametreleriyle, işlevlerimiz artık verilerin bir kopyası yerine gerçek verileri işleyebilir.

Değişkenlerin gerçek değerlerini değiştirmek için, çağıran deyim adresleri bir işlevdeki işaretçi parametrelerine iletir.

Bu eğitimde öğreneceksiniz-

  • İşlevler İşaretçiler Örneği
  • Dizi Parametreli Fonksiyonlar
  • Dizi Döndüren İşlevler
  • İşlev İşaretçileri
  • İşlev İşaretçileri Dizisi
  • Void İşaretçileri Kullanan İşlevler
  • Bağımsız Değişkenler Olarak İşlev İşaretçileri

İşlevler İşaretçiler Örneği

Örneğin, sonraki program ikinin iki değerini değiştirir:

void swap (int *a, int *b);int main() {int m = 25;int n = 100;printf("m is %d, n is %d\n", m, n);swap(&m, &n);printf("m is %d, n is %d\n", m, n);return 0;}void swap (int *a, int *b) {int temp;temp = *a;*a = *b;*b = temp;}}

Çıktı:

m is 25, n is 100m is 100, n is 25

Program, gerçek değişkenlerin değerlerini değiştirir çünkü işlev, işaretçiler kullanarak adreslere erişir. Burada program sürecini tartışacağız:

  1. Parametre olarak iki tamsayı işaretçisi alan ve çağrıldığında herhangi bir değer döndüren iki değişken değerin değiş tokuşundan sorumlu işlevi ilan ederiz.
  2. Ana fonksiyonda, iki tamsayı değişkeni ('m' ve 'n') bildirip başlatıyoruz ve ardından değerlerini sırasıyla yazdırıyoruz.
  3. İki değişkenin adresini ampersand simgesini kullanarak argüman olarak ileterek swap () işlevini çağırırız. Bundan sonra, değişkenlerin yeni takas değerlerini yazdırıyoruz.
  4. Burada, parametre olarak iki tamsayı değişken adresini alan ve ikinci değişkene konulacak değer değişkenlerinden birini kaydetmek için üçüncü bir saklama kutusu olarak kullanılan geçici bir tamsayı değişkeni tanımlayan swap () fonksiyon içeriğini tanımlıyoruz.
  5. 'A' ile gösterilen ilk değişkenin içeriğini geçici değişkende kaydedin.
  6. A ile gösterilen birinci değişkende b ile gösterilen ikinci değişkeni saklayın.
  7. İkinci değişkeni (b ile gösterilen) geçici değişkende kaydedilen ilk değişkenin değeriyle güncelleyin.

Dizi Parametreli Fonksiyonlar

C'de, bir diziyi değere göre bir işleve geçiremeyiz. Halbuki, bir dizi adı bir göstericidir (adres), bu nedenle diziye bir işaretçi iletmek anlamına gelen bir işleve bir dizi adı iletiriz.

Örneğin, aşağıdaki programı ele alıyoruz:

int add_array (int *a, int num_elements);int main() {int Tab[5] = {100, 220, 37, 16, 98};printf("Total summation is %d\n", add_array(Tab, 5));return 0;}int add_array (int *p, int size) {int total = 0;int k;for (k = 0; k < size; k++) {total += p[k]; /* it is equivalent to total +=*p ;p++; */}return (total);}

Çıktı:

 Total summation is 471

Burada program kodunu detayları ile açıklayacağız.

  1. Parametre olarak eleman numarasıyla birlikte bir dizi adresini (işaretçi) alan ve bu elemanların toplam birikmiş toplamını döndüren add_array () işlevini bildirir ve tanımlarız. Gösterici, dizi öğelerini yinelemek için kullanılır (p [k] gösterimini kullanarak) ve toplamı, tüm öğe dizisini yineledikten sonra döndürülecek olan yerel bir değişkende biriktiririz.
  2. Beş tamsayı elemanlı bir tamsayı dizisi bildirir ve başlatırız. Dizi adını (adres görevi görür) ve dizi boyutunu argüman olarak işlev olarak adlandırılan add_array () öğesine ileterek toplam toplamayı yazdırırız .

Dizi Döndüren İşlevler

C'de, aşağıdaki programda olduğu gibi bir diziye bir gösterici döndürebiliriz:

#include int * build_array();int main() {int *a;a = build_array(); /* get first 5 even numbers */for (k = 0; k < 5; k++)printf("%d\n", a[k]);return 0;}int * build_array() {static int Tab[5]={1,2,3,4,5};return (Tab);}

Çıktı:

12345

Ve burada program ayrıntılarını tartışacağız

  1. Tamsayı değeri içeren bir dizi adresi döndüren ve herhangi bir argüman almayan bir işlevi tanımlar ve bildiririz.
  2. İşlev çağrıldıktan sonra oluşturulan dizinin tamamını alan bir tamsayı gösterici bildiririz ve içeriğini beş elemanlı dizinin tamamını yineleyerek yazdırırız.

İşlev tarafından döndürülen dizi adresini saklamak için bir dizi değil, bir göstericinin tanımlandığına dikkat edin. Ayrıca, bir yerel değişken bir işlevden döndürüldüğünde, onu işlevde statik olarak bildirmemiz gerektiğine dikkat edin.

İşlev İşaretçileri

İşaretçilerin herhangi bir bellek konumundaki bir adresi gösterdiklerini tanım gereği bildiğimiz gibi, bellekteki işlevler olarak çalıştırılabilir kodun başlangıcına da işaret edebilirler.

Bir işlev gösterici * ile bildirilir, bildiriminin genel ifadesi şöyledir:

return_type (*function_name)(arguments)

(* İşlev_adı) etrafındaki parantezlerin önemli olduğunu hatırlamalısınız çünkü bunlar olmadan derleyici işlev_adının bir dönüş_türü gösterici döndürdüğünü düşünecektir.

İşlev işaretçisini tanımladıktan sonra, onu bir işleve atamamız gerekir. Örneğin, sonraki program sıradan bir işlevi bildirir, bir işlev işaretçisi tanımlar, işlev işaretçisini sıradan işleve atar ve bundan sonra işlevi işaretçi aracılığıyla çağırır:

#include void Hi_function (int times); /* function */int main() {void (*function_ptr)(int); /* function pointer Declaration */function_ptr = Hi_function; /* pointer assignment */function_ptr (3); /* function call */return 0;}void Hi_function (int times) {int k;for (k = 0; k < times; k++) printf("Hi\n");} 

Çıktı:

HiHiHi

  1. İşlev çağrıldığında parametresi ile gösterilen k kez Hi metni yazdıran standart bir işlevi tanımlıyor ve açıklıyoruz.
  2. Bir tamsayı parametresi alan ve hiçbir şey döndürmeyen bir işaretçi işlevi (özel bildirimi ile) tanımlarız.
  3. İşaretçi işlevimizi Hi_function ile başlatırız, bu da işaretçinin Hi_function () işlevini işaret ettiği anlamına gelir.
  4. İşlev adına bağımsız değişkenlerle dokunarak standart işlev çağırmak yerine, 3 sayısını bağımsız değişken olarak geçirerek yalnızca işaretçi işlevini çağırıyoruz ve işte bu kadar!

İşlev adının, ilk elemanına işaret eden bir dizi adı gibi çalıştırılabilir kodun başlangıç ​​adresini gösterdiğini unutmayın. Bu nedenle, function_ptr = & Hi_function ve (* funptr) (3) gibi talimatlar doğrudur.

NOT: İşlev atama ve işlev çağrısı sırasında adres operatörünü & ve yönlendirme operatörünü * eklemek önemli değildir.

İşlev İşaretçileri Dizisi

Bir dizi işlev işaretçisi, sonraki programda olduğu gibi, karar vermek için bir anahtar veya if ifadesi rolü oynayabilir:

#include int sum(int num1, int num2);int sub(int num1, int num2);int mult(int num1, int num2);int div(int num1, int num2);int main(){ int x, y, choice, result;int (*ope[4])(int, int);ope[0] = sum;ope[1] = sub;ope[2] = mult;ope[3] = div;printf("Enter two integer numbers: ");scanf("%d%d", &x, &y);printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");scanf("%d", &choice);result = ope[choice](x, y);printf("%d", result);return 0;}int sum(int x, int y) {return(x + y);}int sub(int x, int y) {return(x - y);}int mult(int x, int y) {return(x * y);}int div(int x, int y) {if (y != 0) return (x / y); else return 0;}
Enter two integer numbers: 13 48Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2624

Burada program ayrıntılarını tartışıyoruz:

  1. İki tamsayı argümanı alan ve bir tamsayı değeri döndüren dört işlevi açıklar ve tanımlarız. Bu işlevler, kullanıcı tarafından hangi işlevin çağrıldığına ilişkin iki bağımsız değişkeni toplar, çıkarır, çarpar ve böler.
  2. Sırasıyla işlenenleri, işlem türünü ve sonucu işlemek için 4 tam sayı bildiriyoruz. Ayrıca, dört işlevli bir dizi tanımlıyoruz. Dizi öğesinin her bir işlev işaretçisi, iki tamsayı parametresi alır ve bir tamsayı değeri döndürür.
  3. Her bir dizi elemanını önceden bildirilmiş işlevle atar ve başlatırız. Örneğin, üçüncü işlev göstericisi olan üçüncü öğe, çarpma işlemi işlevini gösterecektir.
  4. Klavye ile yazılan kullanıcıdan işlenenleri ve işlem türünü ararız.
  5. Uygun dizi elemanını (Fonksiyon işaretçisi) argümanlarla çağırdık ve uygun fonksiyon tarafından üretilen sonucu depoladık.

Talimat int (* ope [4]) (int, int); işlev işaretçileri dizisini tanımlar. Her dizi öğesi aynı parametrelere ve dönüş türüne sahip olmalıdır.

İfade sonucu = ope [seçim] (x, y); kullanıcı tarafından yapılan seçime göre uygun işlevi çalıştırır Girilen iki tam sayı, işleve iletilen bağımsız değişkenlerdir.

Void İşaretçileri Kullanan İşlevler

İşlev bildirimleri sırasında geçersiz işaretçiler kullanılır. Herhangi bir türü döndürmek için void * dönüş türü izinleri kullanıyoruz. Bir işleve geçerken parametrelerimizin değişmediğini varsayarsak, onu const olarak bildiririz.

Örneğin:

 void * cube (const void *); 

Aşağıdaki programı düşünün:

#include void* cube (const void* num);int main() {int x, cube_int;x = 4;cube_int = cube (&x);printf("%d cubed is %d\n", x, cube_int);return 0;}void* cube (const void *num) {int result;result = (*(int *)num) * (*(int *)num) * (*(int *)num);return result;}

Sonuç:

 4 cubed is 64 

Burada program ayrıntılarını tartışacağız:

  1. Bir tamsayı değeri döndüren ve belirli bir veri türü olmadan değiştirilemez değişkenin adresini alan bir işlevi tanımlayıp bildiriyoruz. Num işaretçisinin işaret ettiği içerik değişkeninin (x) küp değerini hesaplıyoruz ve bir boşluk gösterici olduğu için, belirli bir gösterim (* veri türü) işaretçisi kullanarak onu bir tamsayı veri türüne çevirip yazmalıyız ve geri dönüyoruz küp değeri.
  2. İşleneni ve sonuç değişkenini bildiriyoruz. Ayrıca, işlenenimizi "4" değeriyle başlatıyoruz.
  3. İşlenen adresini ileterek küp fonksiyonunu çağırıyoruz ve sonuç değişkeninde dönen değeri ele alıyoruz

Bağımsız Değişkenler Olarak İşlev İşaretçileri

Bir işlev göstericisini başka bir işleve argüman olarak ileterek yararlanmanın başka bir yolu bazen "geri çağrı işlevi" olarak adlandırılır çünkü alıcı işlev onu "geri çağırır".

Stdlib.h başlık dosyasında, Quicksort "qsort ()" işlevi, bir diziyi sıralamak için ayrılmış bir algoritma olan bu tekniği kullanır.

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void * base: diziye void gösterici.
  • size_t num: Dizi öğesi numarası.
  • size_t genişlik Eleman boyutu.
  • int (* karşılaştırma (const void *, const void *): iki bağımsız değişkenden oluşan ve bağımsız değişkenler aynı değere sahip olduğunda 0, arg1 arg2'den önce geldiğinde <0 ve arg1, arg2'den sonra geldiğinde> 0 döndürür.

Aşağıdaki program, qsort () işlevini kullanarak bir tamsayı dizisini küçükten büyük sayıya doğru sıralar:

#include #include int compare (const void *, const void *);int main() {int arr[5] = {52, 14, 50, 48, 13};int num, width, i;num = sizeof(arr)/sizeof(arr[0]);width = sizeof(arr[0]);qsort((void *)arr, num, width, compare);for (i = 0; i < 5; i++)printf("%d ", arr[ i ]);return 0;}int compare (const void *elem1, const void *elem2) {if ((*(int *)elem1) == (*(int *)elem2)) return 0;else if ((*(int *)elem1) < (*(int *)elem2)) return -1;else return 1;}

Sonuç:

 13 14 48 50 52 

Burada program ayrıntılarını tartışacağız:

  1. İki bağımsız değişkenden oluşan karşılaştırma işlevini tanımlarız ve argümanlar aynı değere sahip olduğunda 0, arg1 arg2'den önce geldiğinde <0 ve arg1 arg2'den sonra geldiğinde> 0 döndürür. (tamsayı)
  2. Bir tamsayı dizisi tanımlar ve başlatırız Dizi boyutu num değişkeninde saklanır ve her dizi elemanının boyutu sizeof () önceden tanımlanmış C operatörü kullanılarak genişlik değişkeninde saklanır.
  3. Qsort işlevini çağırıyoruz ve dizimizi artan düzende sıralamak için daha önce kullanıcı tarafından tanımlanan dizi adını, boyutunu, genişliğini ve karşılaştırma işlevini iletiyoruz.Karşılaştırma, tüm diziye kadar her yinelemede iki dizi öğesi alınarak yapılacaktır. sıralanacak.
  4. Dizimizin iyi sıralandığından emin olmak için tüm diziyi for döngüsü kullanarak yineleyerek dizi öğelerini yazdırırız.