ตัวชี้ฟังก์ชั่นในการเขียนโปรแกรม C พร้อมตัวอย่าง

พอยน์เตอร์ให้ความเป็นไปได้อย่างมากกับฟังก์ชัน 'C' ซึ่งเราจำกัดให้ส่งคืนค่าเดียว ด้วยพารามิเตอร์ตัวชี้ ขณะนี้ฟังก์ชันของเราสามารถประมวลผลข้อมูลจริง แทนที่จะคัดลอกข้อมูล

เพื่อที่จะแก้ไขค่าที่แท้จริงของตัวแปร คำสั่งการเรียกจะส่งที่อยู่ไปยังพารามิเตอร์ตัวชี้ในฟังก์ชัน

ตัวอย่างพอยน์เตอร์ฟังก์ชัน

ตัวอย่างเช่น โปรแกรมถัดไปจะสลับค่าสองค่าจากสองค่า:

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;}
}

Output:

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

ตัวอย่างพอยน์เตอร์ฟังก์ชัน

โปรแกรมจะสลับค่าตัวแปรจริงเนื่องจากฟังก์ชันเข้าถึงโดยใช้ที่อยู่ ตัวชี้- ที่นี่เราจะหารือเกี่ยวกับกระบวนการของโปรแกรม:

  1. เราประกาศฟังก์ชันที่รับผิดชอบในการสลับค่าตัวแปรสองตัว ซึ่งรับตัวชี้จำนวนเต็มสองตัวเป็นพารามิเตอร์ และส่งคืนค่าใดๆ เมื่อมีการเรียกใช้
  2. ในฟังก์ชันหลัก เราประกาศและเริ่มต้นตัวแปรจำนวนเต็มสองตัว ('m' และ 'n') จากนั้นเราจะพิมพ์ค่าตามลำดับ
  3. เราเรียกฟังก์ชัน swap() โดยส่งที่อยู่ของตัวแปรทั้งสองเป็นอาร์กิวเมนต์โดยใช้สัญลักษณ์แอมเพอร์แซนด์ หลังจากนั้น เราจะพิมพ์ค่าที่สลับใหม่ของตัวแปร
  4. ที่นี่เราจะกำหนดเนื้อหาของฟังก์ชัน swap() ซึ่งรับที่อยู่ตัวแปรจำนวนเต็มสองตัวเป็นพารามิเตอร์ และประกาศตัวแปรจำนวนเต็มชั่วคราวที่ใช้เป็นกล่องจัดเก็บข้อมูลที่สามเพื่อบันทึกตัวแปรค่าตัวหนึ่งที่จะใส่ไว้ในตัวแปรที่สอง
  5. บันทึกเนื้อหาของตัวแปรแรกที่ชี้โดย 'a' ในตัวแปรชั่วคราว
  6. เก็บตัวแปรตัวที่สองที่ชี้โดย b ไว้ในตัวแปรตัวแรกที่ชี้โดย a
  7. อัพเดตตัวแปรตัวที่สอง (ชี้โดย b) ด้วยค่าของตัวแปรตัวแรกที่บันทึกไว้ในตัวแปรชั่วคราว

ฟังก์ชั่นที่มีพารามิเตอร์อาร์เรย์

ในภาษา C เราไม่สามารถส่งอาร์เรย์ตามค่าไปยังฟังก์ชันได้ ในขณะที่ชื่ออาร์เรย์คือตัวชี้ (ที่อยู่) ดังนั้นเราจึงส่งชื่ออาร์เรย์ไปยังฟังก์ชันซึ่งหมายถึงการส่งผ่านตัวชี้ไปยังอาร์เรย์

ตัวอย่างเช่น เราพิจารณาโปรแกรมต่อไปนี้:

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);}

Output:

 Total summation is 471

ที่นี่เราจะอธิบายโค้ดโปรแกรมพร้อมรายละเอียด

ฟังก์ชั่นที่มีพารามิเตอร์อาร์เรย์

  1. เราประกาศและกำหนดฟังก์ชัน add_array() ซึ่งรับที่อยู่อาร์เรย์ (ตัวชี้) พร้อมด้วยหมายเลของค์ประกอบเป็นพารามิเตอร์ และส่งคืนผลรวมสะสมขององค์ประกอบเหล่านี้ ตัวชี้ใช้เพื่อวนซ้ำองค์ประกอบอาร์เรย์ (โดยใช้สัญลักษณ์ p[k]) และเราสะสมผลรวมในตัวแปรท้องถิ่นซึ่งจะถูกส่งกลับหลังจากการวนซ้ำอาร์เรย์องค์ประกอบทั้งหมด
  2. เราประกาศและเริ่มต้นอาร์เรย์จำนวนเต็มด้วยองค์ประกอบจำนวนเต็มห้าองค์ประกอบ เราพิมพ์ผลรวมทั้งหมดโดยส่งชื่ออาร์เรย์ (ซึ่งทำหน้าที่เป็นที่อยู่) และขนาดอาร์เรย์ไปที่ add_array()เรียกว่าฟังก์ชันเป็นอาร์กิวเมนต์

ฟังก์ชั่นที่ส่งกลับอาร์เรย์

ใน C เราสามารถส่งคืนตัวชี้ไปยังอาร์เรย์ได้ เช่นเดียวกับในโปรแกรมต่อไปนี้:

#include <stdio.h>
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);}

Output:

1
2
3
4
5

และที่นี่เราจะมาพูดถึงรายละเอียดของโปรแกรม

ฟังก์ชั่นที่ส่งกลับอาร์เรย์

  1. เรากำหนดและประกาศฟังก์ชันที่ส่งคืนที่อยู่อาร์เรย์ที่มีค่าจำนวนเต็มและไม่ได้รับอาร์กิวเมนต์ใดๆ
  2. เราประกาศตัวชี้จำนวนเต็มซึ่งรับอาร์เรย์ที่สมบูรณ์ที่สร้างขึ้นหลังจากเรียกใช้ฟังก์ชัน และเราพิมพ์เนื้อหาโดยการวนซ้ำอาร์เรย์ทั้งห้าองค์ประกอบ

โปรดสังเกตว่าตัวชี้ไม่ใช่อาร์เรย์ถูกกำหนดไว้เพื่อจัดเก็บที่อยู่อาร์เรย์ที่ส่งคืนโดยฟังก์ชัน โปรดสังเกตด้วยว่าเมื่อตัวแปรท้องถิ่นถูกส่งกลับจากฟังก์ชัน เราต้องประกาศให้เป็นค่าคงที่ในฟังก์ชัน

ตัวชี้ฟังก์ชัน

ดังที่เราทราบตามคำจำกัดความว่าตัวชี้ชี้ไปยังที่อยู่ในตำแหน่งหน่วยความจำใดๆ ตัวชี้ยังสามารถชี้ไปที่จุดเริ่มต้นของโค้ดที่ปฏิบัติการได้เป็นฟังก์ชันในหน่วยความจำ
ตัวชี้ไปยังฟังก์ชันถูกประกาศด้วย * คำสั่งทั่วไปของการประกาศคือ:

return_type (*function_name)(arguments)

คุณต้องจำไว้ว่าวงเล็บรอบๆ (*function_name) มีความสำคัญ เพราะหากไม่มีวงเล็บ คอมไพลเลอร์จะคิดว่า function_name กำลังส่งคืนพอยน์เตอร์เป็น return_type
หลังจากกำหนดฟังก์ชันพอยน์เตอร์แล้ว เราต้องกำหนดค่าให้กับฟังก์ชัน ตัวอย่างเช่น โปรแกรมถัดไปจะประกาศฟังก์ชันทั่วไป กำหนดฟังก์ชันพอยน์เตอร์ กำหนดฟังก์ชันพอยน์เตอร์ให้กับฟังก์ชันทั่วไป จากนั้นจึงเรียกใช้ฟังก์ชันผ่านพอยน์เตอร์:

#include <stdio.h>
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");}

Output:

Hi
Hi
Hi

ฟังก์ชันพอยน์เตอร์ในภาษาซี

  1. เรากำหนดและประกาศฟังก์ชันมาตรฐานซึ่งจะพิมพ์ข้อความ Hi k ครั้งที่ระบุโดยพารามิเตอร์ครั้งเมื่อมีการเรียกใช้ฟังก์ชัน
  2. เรากำหนดฟังก์ชันตัวชี้ (พร้อมการประกาศพิเศษ) ซึ่งรับพารามิเตอร์จำนวนเต็มและไม่ส่งคืนอะไรเลย
  3. เราเริ่มต้นฟังก์ชันตัวชี้ของเราด้วย Hi_function ซึ่งหมายความว่าตัวชี้ชี้ไปที่ Hi_function()
  4. แทนที่จะเรียกใช้ฟังก์ชันมาตรฐานโดยการแตะชื่อฟังก์ชันพร้อมกับอาร์กิวเมนต์ เราจะเรียกเฉพาะฟังก์ชันพอยน์เตอร์โดยส่งหมายเลข 3 เป็นอาร์กิวเมนต์ แค่นั้นเอง!

โปรดทราบว่าชื่อฟังก์ชันชี้ไปยังที่อยู่เริ่มต้นของโค้ดที่ปฏิบัติการได้ เช่น ชื่ออาร์เรย์ที่ชี้ไปยังองค์ประกอบแรก ดังนั้นคำสั่งเช่น function_ptr = &Hi_function และ (*funptr)(3) จึงถูกต้อง
หมายเหตุ: ไม่จำเป็นต้องแทรกตัวดำเนินการที่อยู่ & และตัวดำเนินการทางอ้อม * ในระหว่างการกำหนดฟังก์ชันและการเรียกใช้ฟังก์ชัน

อาร์เรย์ของพอยน์เตอร์ฟังก์ชัน

อาร์เรย์ของพอยน์เตอร์ฟังก์ชันสามารถมีบทบาทเป็นสวิตช์หรือคำสั่ง if ในการตัดสินใจได้ ดังเช่นในโปรแกรมถัดไป:

#include <stdio.h>
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 48
Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2
624

เราจะมาพูดถึงรายละเอียดของโปรแกรมกันดังนี้:

อาร์เรย์ของพอยน์เตอร์ฟังก์ชัน

  1. เราประกาศและกำหนดสี่ ฟังก์ชั่น ซึ่งรับอาร์กิวเมนต์จำนวนเต็มสองตัวและส่งกลับค่าจำนวนเต็ม ฟังก์ชันเหล่านี้บวก ลบ คูณ และหารอาร์กิวเมนต์ทั้งสองที่เกี่ยวข้องกับฟังก์ชันที่ผู้ใช้ถูกเรียกใช้
  2. เราประกาศจำนวนเต็ม 4 ตัวเพื่อจัดการกับตัวดำเนินการ ประเภทการดำเนินการ และผลลัพธ์ตามลำดับ นอกจากนี้ เรายังประกาศอาร์เรย์ของตัวชี้ฟังก์ชัน XNUMX ตัว ตัวชี้ฟังก์ชันแต่ละตัวขององค์ประกอบอาร์เรย์จะรับพารามิเตอร์จำนวนเต็ม XNUMX ตัวและส่งคืนค่าจำนวนเต็ม
  3. เรากำหนดและกำหนดค่าเริ่มต้นให้กับแต่ละองค์ประกอบของอาร์เรย์ด้วยฟังก์ชันที่ประกาศไว้แล้ว ตัวอย่างเช่น องค์ประกอบที่สามซึ่งเป็นฟังก์ชันตัวชี้ที่สามจะชี้ไปที่ฟังก์ชันการดำเนินการคูณ
  4. เราค้นหาตัวดำเนินการและประเภทการดำเนินการจากผู้ใช้ที่พิมพ์ด้วยแป้นพิมพ์
  5. เราเรียกองค์ประกอบอาร์เรย์ที่เหมาะสม (ตัวชี้ฟังก์ชัน) พร้อมอาร์กิวเมนต์ และเราเก็บผลลัพธ์ที่สร้างโดยฟังก์ชันที่เหมาะสม

คำสั่ง int (*ope[4])(int, int); กำหนดอาร์เรย์ของพอยน์เตอร์ฟังก์ชัน องค์ประกอบอาร์เรย์แต่ละรายการจะต้องมีพารามิเตอร์และประเภทการส่งคืนเหมือนกัน
ผลลัพธ์ของคำสั่ง = ope[choice](x, y); รันฟังก์ชันที่เหมาะสมตามตัวเลือกที่ผู้ใช้เลือก จำนวนเต็มสองตัวที่ป้อนคืออาร์กิวเมนต์ที่ส่งผ่านไปยังฟังก์ชัน

ฟังก์ชั่นการใช้ตัวชี้โมฆะ

พอยน์เตอร์เป็นโมฆะถูกใช้ในระหว่างการประกาศฟังก์ชัน เราใช้ใบอนุญาตประเภทการคืนสินค้าเป็นโมฆะ * เพื่อคืนประเภทใดก็ได้ หากเราถือว่าพารามิเตอร์ของเราไม่เปลี่ยนแปลงเมื่อส่งผ่านไปยังฟังก์ชัน เราจะประกาศให้เป็น const
ตัวอย่างเช่น:

 void * cube (const void *);

พิจารณาโปรแกรมต่อไปนี้:

#include <stdio.h>
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;}

ผลลัพธ์:

 4 cubed is 64

ที่นี่เราจะหารือรายละเอียดของโปรแกรม:

ฟังก์ชั่นการใช้ตัวชี้โมฆะ

  1. เรากำหนดและประกาศฟังก์ชันที่ส่งคืนค่าจำนวนเต็มและรับที่อยู่ของตัวแปรที่ไม่สามารถเปลี่ยนแปลงได้โดยไม่มีประเภทข้อมูลเฉพาะ เราคำนวณค่าคิวบ์ของตัวแปรเนื้อหา (x) ชี้โดยตัวชี้ num และเนื่องจากเป็นตัวชี้เป็นโมฆะ เราจึงต้องพิมพ์เป็นชนิดข้อมูลจำนวนเต็มโดยใช้สัญกรณ์เฉพาะ (* ประเภทข้อมูล) แล้วเราจะส่งคืน ค่าคิวบ์
  2. เราประกาศตัวดำเนินการและตัวแปรผลลัพธ์ และกำหนดค่าเริ่มต้นตัวดำเนินการด้วยค่า “4”
  3. เราเรียกใช้ฟังก์ชันลูกบาศก์โดยส่งที่อยู่ตัวดำเนินการ และเราจัดการค่าที่ส่งกลับในตัวแปรผลลัพธ์

ตัวชี้ฟังก์ชันเป็นอาร์กิวเมนต์

อีกวิธีในการใช้ประโยชน์จากตัวชี้ฟังก์ชันโดยส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันอื่นซึ่งบางครั้งเรียกว่า "ฟังก์ชันเรียกกลับ" เนื่องจากฟังก์ชันรับ "เรียกกลับ"
ในไฟล์ส่วนหัว stdlib.h ฟังก์ชัน Quicksort “qsort()” ใช้เทคนิคนี้ซึ่งเป็นอัลกอริธึมที่ใช้เพื่อจัดเรียงอาร์เรย์โดยเฉพาะ

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void *base : โมฆะตัวชี้ไปยังอาร์เรย์
  • size_t num : หมายเลของค์ประกอบอาร์เรย์
  • ความกว้าง size_t ขนาดองค์ประกอบ
  • int (*compare (const void *, const void *) : ตัวชี้ฟังก์ชันประกอบด้วยสองอาร์กิวเมนต์และส่งคืนค่า 0 เมื่ออาร์กิวเมนต์มีค่าเท่ากัน <0 เมื่อ arg1 มาก่อน arg2 และ >0 เมื่อ arg1 มาก่อน arg2

โปรแกรมต่อไปนี้จะเรียงลำดับอาร์เรย์จำนวนเต็มจากตัวเลขน้อยไปหามากโดยใช้ฟังก์ชัน qsort():

#include <stdio.h>
#include <stdlib.h>
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;}

ผลลัพธ์:

 13 14 48 50 52

ที่นี่เราจะหารือรายละเอียดของโปรแกรม:

ตัวชี้ฟังก์ชันเป็นอาร์กิวเมนต์

  1. เรากำหนดฟังก์ชันการเปรียบเทียบที่ประกอบด้วยสองอาร์กิวเมนต์และส่งคืนค่า 0 เมื่ออาร์กิวเมนต์มีค่าเท่ากัน <0 เมื่อ arg1 มาก่อน arg2 และ >0 เมื่อ arg1 มาก่อน arg2 พารามิเตอร์เป็นประเภทตัวชี้โมฆะที่ส่งไปยังประเภทข้อมูลอาร์เรย์ที่เหมาะสม (จำนวนเต็ม)
  2. เรากำหนดและเริ่มต้นอาร์เรย์จำนวนเต็ม ขนาดอาร์เรย์จะถูกเก็บไว้ใน NUM ตัวแปรและขนาดของแต่ละองค์ประกอบอาร์เรย์จะถูกเก็บไว้ในตัวแปรความกว้างโดยใช้ sizeof() ที่กำหนดไว้ล่วงหน้า ตัวดำเนินการ C.
  3. เราเรียก เรียงลำดับ และส่งผ่านชื่ออาร์เรย์ ขนาด ความกว้าง และฟังก์ชันการเปรียบเทียบที่กำหนดก่อนหน้านี้โดยผู้ใช้ เพื่อจัดเรียงอาร์เรย์ของเราตามลำดับจากน้อยไปหามาก การเปรียบเทียบจะดำเนินการโดยนำองค์ประกอบอาร์เรย์สองรายการในการวนซ้ำแต่ละครั้ง จนกระทั่งอาร์เรย์ทั้งหมดจะถูกจัดเรียง
  4. เราพิมพ์องค์ประกอบอาร์เรย์เพื่อให้แน่ใจว่าอาร์เรย์ของเราได้รับการจัดเรียงอย่างดีโดยการวนซ้ำอาร์เรย์ทั้งหมดโดยใช้ สำหรับห่วง.