- เหมือนกันทั้ง C และ C++
- ฟังก์ชันต่างๆ ที่ภาษา C และ C++ กำหนดให้ มีรูปแบบการใช้งานในรูป
functionName(arg1, arg2, ...) - เมื่อโค้ดอ่านถึงส่วนที่เรียกใช้ฟังก์ชัน โปรแกรมจะ
- จำสถานะของฟังก์ชันเดิมที่เรียกใช้ (เช่น
main) - คัดลอกค่าจาก argument ไปให้ฟังก์ชัน (ถ้ามี)
- ฟังก์ชันจะทำงาน หากฟังก์ชันส่งค่ากลับมา ค่าจะมาอยู่แทนที่ตำแหน่งที่เรียกฟังก์ชัน
- จำสถานะของฟังก์ชันเดิมที่เรียกใช้ (เช่น
- ฟังก์ชันที่ถูกเรียก จะไม่ทราบ local variable ของฟังก์ชันที่เรียกใช้ (ต่อเรื่อง scope)
ตัวอย่าง
int a = pow(2, 3);
// pow(2, 3) เมื่อคำนวณเสร็จแล้ว จะทำให้โค้ดมีลักษณะคล้าย int a = 8;
printf("%d", a);
// printf ไม่ส่งค่าใดๆ ที่เราจำเป็นต้องใช้กลับมา ดังนั้นจึงเรียกโดดๆได้เลย
printf("%d", pow(2, 3));
// pow(2, 3) อาจมาแทนที่เป็น argument ของฟังก์ชันอื่นอีกได้เลย
// ได้เป็น printf("%d", 8);
getch();
// บางฟังก์ชันไม่จำเป็นต้องใช้ argument- เราสามารถสร้างฟังก์ชันขึ้นได้เอง โดยโปรแกรมที่มีการประกาศฟังก์ชัน จะมีลักษณะดังนี้
#include <stdio.h>
int sum(int x, int y) // ฟังก์ชันที่ผู้ใช้สร้างขึ้น
{
int s = x + y;
return s;
}
int main(void)
{
int a, b;
scanf("%d", &a);
scanf("%d", &b);
printf("%d", sum(a, b));
// sum(a, b) จะถูกแทนที่ด้วยค่าของ a + b
}- สังเกตว่ารูปแบบการประกาศฟังก์ชันจะเป็นดังนี้
returnType functionName(argType1 argName1, argType2 argName2, ...)
{
// statements
return something; // ถ้า returnType เป็น void ไม่ต้องมีบรรทัดนี้
}- returnType คือ ชนิดของตัวแปรที่ต้องการคืนค่ากลับมา หากไม่ต้องการคืน ให้ใส่
void - functionName คือ ชื่อของฟังก์ชันที่ต้องการ ฟังก์ชันอื่นจะเรียกฟังก์ชันนี้ผ่านชื่อที่ระบุตรงนี้
- argType คือ ชนิดของ argument/parameter ที่ต้องการรับ
- argName คือ ชื่อของ parameter ที่ตัวฟังก์ชันจะใช้เรียก
- สังเกตว่าชื่อตัวแปรตอนเรียกฟังก์ชันไม่ต้องตรงกับชื่อตัวแปรในนิยาม เช่น
sum(a, b)แต่ฟังก์ชันประกาศเป็นint sum(int x, int y) - เพราะฟังก์ชันจะคัดลอกค่าจากตัวแปรแต่ละตัว ไปใส่ในตัวแปรที่เราประกาศตรงหัวฟังก์ชัน
- สังเกตว่าชื่อตัวแปรตอนเรียกฟังก์ชันไม่ต้องตรงกับชื่อตัวแปรในนิยาม เช่น
- หากฟังก์ชันมีการส่งค่ากลับมา ควรเรียกใช้ฟังก์ชันตามหัวข้อข้างบน
- การประกาศฟังก์ชัน จะมีผลให้ฟังก์ชันที่อยู่ข้างล่างเรียกใช้ได้เท่านั้น ส่วนข้างบนจะใช้ไม่ได้
- ต้องประกาศฟังก์ชันก่อนฟังก์ชันที่เรียกใช้ (เช่น
main)
- ต้องประกาศฟังก์ชันก่อนฟังก์ชันที่เรียกใช้ (เช่น
- Prototype เป็นการประกาศฟังก์ชันที่ระบุเพียงแค่ชื่อฟังก์ชัน argument และ return type เท่านั้น
- มีไว้เพื่อให้ฟังก์ชันอื่นๆ ที่ต้องการเรียกใช้ รับทราบว่าฟังก์ชันนี้มีอยู่จริง
- ส่วนรายละเอียดการทำงานของฟังก์ชัน สามารถระบุไว้ได้ที่อื่น
- ทำได้หลายแบบ แต่วิธีที่ขอกล่าว ณ ที่นี้คือการคัดลอกหัวฟังก์ชันมา เพื่อจะได้ไม่งง
- จากตัวอย่างข้างบน เราสามารถย้าย
sumลงมาข้างล่างmainแล้วประกาศ prototype ของsumข้างบนได้ดังนี้
#include <stdio.h>
int sum(int x, int y); // prototype ที่ประกาศโดยคัดลอกหัวฟังก์ชันมา
int main(void)
{
int a, b;
scanf("%d", &a);
scanf("%d", &b);
printf("%d", sum(a, b));
// sum(a, b) จะถูกแทนที่ด้วยค่าของ a + b
}
int sum(int x, int y) // หัวฟังก์ชันที่ประกาศ
{
int s = x + y;
return s;
}- ดังที่ระบุไว้ในหัวข้อการเรียกใช้ฟังก์ชัน การเรียกฟังก์ชันนั้นจะคัดลอกค่ามาใส่ในตัวแปร parameter
- ดังนั้น การแก้ไขตัวแปรใดๆ ภายในฟังก์ชันจะไม่ส่งผลต่อค่าเดิมข้างนอกฟังก์ชัน
ตัวอย่าง
#include <stdio.h>
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
// here, a = 5, a = 3
}
int main(void)
{
int a = 3;
int b = 5;
swap(a, b); // but after this, a = 3, b = 5
printf("a is %d. b is %d.", a, b);
}
// Output:
// a is 3. b is 5.- สังเกตว่าฟังก์ชันตัวอย่าง ไม่ได้สลับค่าตัวแปร
aกับbของmainแต่อย่างใด เพราะswapสลับแค่ตัวแปรภายในฟังก์ชันตัวเองเท่านั้น - ทั้งนี้ทั้งนั้น ลักษณะการเรียกฟังก์ชันแบบ Pass by Value จึงสามารถอธิบายได้ว่าทำไมเราถึงเรียกฟังก์ชันด้วยค่าคงที่ได้
- ดังตัวอย่างแรกสุด
pow(2, 3)สังเกตว่า 2 กับ 3 ไม่ได้อยู่ในตัวแปรใดๆ ทั้งสิ้น
- ดังตัวอย่างแรกสุด
-
หากเราต้องการให้ฟังก์ชันแก้ไขตัวแปรของเราได้ ฟังก์ชันจะต้องรับ ตำแหน่งที่อยู่ตัวแปร แทนค่าของตัวแปร ซึ่งก็คือ pointer
-
เมื่อฟังก์ชันทราบตำแหน่งที่อยู่ตัวแปร ฟังก์ชันสามารถเข้าถึงค่าที่ตำแหน่งนั้น และแก้ไขได้อย่างถูกต้อง
-
การประกาศตัวแปร pointer สามารถทำได้โดยเติมเครื่องหมาย asterisk * หลังชนิดตัวแปร
-
หากต้องการทราบตำแหน่งของตัวแปรใดๆ ให้ใส่เครื่องหมาย ampersand & นำหน้าตัวแปรนั้นๆ
-
หากต้องการเข้าถึงตัวแปรผ่าน pointer ให้ใส่เครื่องหมาย asterisk * นำหน้าชื่อตัวแปร pointer
#include <stdio.h>
// swap รับ int pointer 2 ตัว โดยเรียกว่า a และ b
void swap(int *a, int *b)
{
int temp = *a; // นำค่าที่ a ชี้อยู่ ใส่ลงไปใน temp
*a = *b; // นำค่าที่ b ชี้อยู่ ใส่ลงไปในที่ที่ a ชี้เลย
*b = temp; // นำค่าของ temp ใส่ลงไปที่ที่ b ชี้
}
int main(void)
{
int a = 3;
int b = 5;
swap(&a, &b); // ส่งตำแหน่งที่อยู่ของ a และ b ไปให้ swap ทำให้ swap สามารถแก้ไขค่าได้
printf("a is %d. b is %d.", a, b);
}
// Output:
// a is 5. b is 3.- ส่วนนี้ใช้ได้กับภาษา C++ เท่านั้น
- นอกจาก pointer ในภาษา C ภาษา C++ ยังมีสิ่งที่เรียกว่า reference ซึ่งทำงานคล้ายคลึงกับ pointer
- การประกาศให้ฟังก์ชันรับตัวแปร reference สามารถทำได้โดยเติมเครื่องหมาย ampersand & หลังชนิดตัวแปร
- ตัวแปร reference จะจัดการเรื่องการเก็บที่อยู่ และการเข้าถึงค่าให้อัตโนมัติ สามารถใช้เหมือนตัวแปรทั่วไปได้เลย
- ไม่ต้องเติม & ข้างหน้าชื่อตัวแปรเพื่อส่งตำแหน่งตัวแปรเวลาเรียกใช้ฟังก์ชัน
- ไม่ต้องเติม * ข้างหน้าชื่อตัวแปร reference เพื่อเข้าถึงค่าของตัวแปรนั้นๆ
#include <iostream>
using namespace std;
// swap รับ int reference 2 ตัว โดยเรียกว่า a และ b
void swap(int &a, int &b)
{
int temp = a; // สามารถเรียกใช้แบบตัวแปรทั่วไปได้เลยโดยไม่ต้องสนว่า a เป็น reference
a = b; // แต่เมื่อมีการเปลี่ยนแปลงค่า a และ b ในนี้ ค่าที่ reference ชี้อยู่ (และจัดการให้อัตโนมัติ) ก็จะเปลี่ยนแปลงตาม
b = temp;
}
int main()
{
int a = 3;
int b = 5;
swap(a, b); // ระบบจะจัดการส่งที่อยู่ของ a และ b ใปให้โดยอัตโนมัติ
cout << "a is " << a << ". b is " << b << ".";
}
// Output:
// a is 5. b is 3.- ฟังก์ชัน
swapแบบ reference ที่ยกมานี้ มีอยู่แล้วใน#include <algorithm>ซึ่งสามารถใช้ได้กับตัวแปรทุกชนิด
- เหมือนกันทั้ง C และ C++
- หาก array ที่รับไม่มีขนาดที่แน่นอน ควรจะรับขนาดของ array มาด้วย เพื่อการ loop
#include <stdio.h>
void printStudents(int studentID[], int n)
{
for (int i = 0; i < n; i++)
printf("Student #%d: ID %d\n", i + 1, studentID[i]);
}
int main()
{
int students[] = { 1652, 5830, 2601, 3524 };
printStudents(students, 4);
}
// Output:
// Student #1: ID 1652
// Student #2: ID 5830
// Student #3: ID 2601
// Student #4: ID 3524- หากต้องการส่งค่ากลับเป็น array ควรให้ฟังก์ชันที่เรียกใช้ เตรียม array ไว้ แล้วเราจึงแก้ไข array นั้น
- เช่น
scanfกับ string จะสังเกตได้ว่า เราต้องประกาศตัวแปรchar []ก่อน แล้วscanfจึงจะทำหน้าที่เปลี่ยนข้อความของเราให้
- เช่น
- เนื่องจาก array ที่ส่งมามีลักษณะเป็น pointer จึงสามารถแก้ไขสมาชิกแต่ละตัวได้โดยตรง เหมือน Pass by Reference
- แต่ไม่สามารถกำหนดให้เป็น array ชุดใหม่ได้
- อีกวิธีหนึ่ง คือการสร้าง array ด้วยการ
mallocแล้วส่ง pointer กลับมา (ผู้ใช้มีหน้าที่free) ซึ่งจะได้เรียนในเรื่อง pointer