Objective-C Programming Chapter 6

Chapter 6

Function , Pointer

การเขียนโปรแกรมโดยปกติมักจะพูดถึงเรื่องฟังก์ชันก่อนการเขียนคลาสและเมธอด แต่เนื่องจากฟังก์ชันมีความคล้ายกันกับเมธอด และเป็นเนื้อหาเกี่ยวกับภาษา C มากกว่า หนังสือเล่มนี้จึงเริ่มด้วยการคลาสและเมธอดก่อนฟังก์ชัน หากผู้รู้เรื่องฟังก์ชันและพ้อยเตอร์มาแล้วก็ยังแนะนำให้อ่านทบทวน เพราะเราจะลงลึกในส่วนของทำงานของระบบคอมพิวเตอร์เพื่อทำความเข้าใจถึงที่มาที่ไปของฟังก์ชันและพ้อยเตอร์
ในบทก่อนๆเราได้พูดถึงคำว่า “ฟังก์ชัน” อยู่หลายครั้ง อีกทั้งได้เรียกใช้งานฟังก์ชันต่างๆ เป็นต้นว่า NSLog ไปบ้างแล้ว ส่วนบทนี้เราจะเรียนรู้เกี่ยวกับฟังก์ชันในภาษา C เพื่อที่จะนำไปต่อยอดกับความสามารถใหม่ของภาษา Objective-C เช่น Grand Central Dispatch และ Block นอกจากนี้เราจะได้ศึกษาการใช้งานบางส่วนของ C Standard Library ซึ่งเป็นฟังก์ชันพื้นฐานของภาษา C และ Objective-C
ฟังก์ชันมีความคล้ายคลึงกับเมธอดของอ็อบเจ็กนั่นคือเป็นกลุ่มของคำสั่งๆต่าง ที่ทำงานด้วยกันเพื่อจุดประสงค์บางอย่าง เป็นต้นว่า ถ้าหากต้องเปรียบเทียบค่ามากกว่าน้อยกว่าของนักเรียนทั้งชั้น สิ่งที่แตกต่างระหว่างฟังก์ชันกับเมธอดก็คือไม่ต้องประกาศ Class และ Instance เพื่อเรียกใช้งาน

Function Definition

การประกาศฟังก์ชันในภาษา C มีรูปแบบการประกาศดังนี้
function

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

Program 6.1
main.m

Program 6.1 Output
Max(10 , 20) is 20
Max(20 , 30) is 30
Max(10 , 30) is 30

จากโค้ดของโปรแกรมตัวอย่าง การเรียกใช้ฟังก์ชันทำได้ง่ายๆเพียงแค่เริ่มต้นด้วยชื่อของฟังก์ชันและตามด้วยเครื่องหมาย “(“ วงเล็บเปิด จากนั้นต่อท้ายด้วยพารามิเตอร์แต่ละตัว ซึ่งคั่นด้วยเครื่องหมาย , และปิดท้ายด้วยเครื่องหมาย “)” วงเล็บปิด เราจะเขียนโปรแกรมอีกสักโปรแกรม โดยโปรแกรมคำนวนหาค่า Prime Number หรือจำนวนเฉพาะโดยเริ่มจาก 2 ไปจนถึงจำนวนที่กำหนด  ซึ่งมีโค้ดง่ายๆดังต่อไปนี้

Program 6.2
main.m

Program 6.2 Output
2
3
5
7
9
11
13
17
19

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

Function Prototype

ถ้าสังเกตโค้ดของสองโปรแกรมที่ผ่านมาจะพบว่า เราต้องเขียนฟังก์ชันอยู่ก่อนโค้ดในส่วน main เสมอ และโปรแกรมที่ 6.2 เราไม่สามารถเขียนฟังก์ชัน printPrime ก่อน isPrime ได้ หากเราสลับโค้ดโดยเขียนฟังก์ชัน printPrime โปรแกรมจะเกิดข้อผิดพลาดไม่สามารถคอมไพล์ได้

error_function

อย่างไรก็ตามเราสามารถแก้ปัญหานี้ได้ด้วยการประกาศ Function Prototype หรือเป็นการบอกกับคอมไพลเลอร์ว่าโค้ดของฟังก์ชันเราได้เตรียมไว้ให้แล้ว วิธีการประกาศ function prototype ก็เพียงแค่ประกาศฟังก์ชัน โดยที่ไม่ต้องเขียนส่วน implement เราจะแก้ไขโปรแกรม 6.2 โดยเพิ่ม function prototype

Program 6.3
main.m

บรรทัดที่ 4-5 เป็นการประกาศ function prototype เพื่อบอกให้คอมไพลเลอร์รู้ว่ามีฟังก์ชันเหล่านี้อยู่ หลังจากนั้น เราจะเขียนฟังก์ชันไว้ส่วนใดๆของโปรแกรมก็ได้ ไม่จำเป็นต้องเขียนก่อน main program เสมอไป จากตัวอย่างเราได้เขียนส่วนของฟังก์ชัน isPrime ไว้ท้ายของโปรแกรม

Recursive Function

นอกจากฟังก์ชันจะสามารถเรียกใช้ฟังก์ชันอื่นได้แล้ว ฟังก์ชันยังสามารถเรียกใช้ตัวมันเองได้อีกด้วย การกระทำแบบนี้เราเรียกว่า recursive function เราจะเขียนฟังก์ชันแบบ recursive กันสักโปรแกรมเพื่อหาค่า factorial เช่น factorial ของ 5 ก็คือ 5 x 4 x 3 ไปเรื่อยจนถึง 1 ซึ่งมีค่าเท่ากับ 120 โค้ดของฟังก์ชัน factorial ในรูปแบบปกติเราอาจจะเขียนได้ดังนี้

จากฟังก์ชันดังกล่าวหากเขียนในรูปแบบของ recursive function จะได้ว่า

Program 6.4
main.m

Program 6.4 Output
Factorial(5) = 120
โค้ดของ factorial ในโปรแกรม 6.4 จะทำการเปรียบเทียบค่า n หากไม่เท่ากับ 0 ก็็จะเรียกฟังก์ชัน factorial ซึ่งเป็นการเรียกตัวมันเองโดยส่งค่า n-1 เป็นพารามิเตอร์ จะเห็นว่า factorial จะเรียกตัวมันเองไปเรื่อยๆ เพื่อให้ง่ายต่อความเข้าใจ ดูแผนภาพต่อไปนี้ประกอบ

recursive

ฟังก์ชัน factorial จะเรียกตัวเองซ้ำไปเรื่อยๆจนกว่าจะถึงค่า n = 0 และจะส่งค่า 1 กลับมายังฟังก์ชัน factorial(1) ที่เป็นผู้เรียก การส่งค่ากลับจะทำตามลำดับชั้นย้อนขึ้นเรื่อยมาจนถึงจุดแรกที่เริ่มเรียกฟังก์ชันนั่นก็คือ main
การทำงานแบบ recursive เมื่อเทียบกับฟังก์ชันที่เป็น iteration (การวนลูปเป็นรอบๆ) มีข้อเสียคือ ใช้หน่วยความจำมากกว่า จากรูปจะเห็นว่าพื้นของหน่วยความจำสำหรับการเรียกฟังก์ชั่น factorial ขึ้นอยู่กับจำนวน n เช่น n = 5 ก็จะใช้พื้นที่ถึง 6 ฟังก์ชันด้วยกัน นอกจากนี้ recursive function มีการทำงานที่ซับซ้อนกว่า และทำงานได้ช้ากว่าแบบ iteration อย่างไรก็ตาม resursive function มีข้อดีคือ เหมาะสำหรับการคำนวนหรือการแก้ปัญหา บางอย่าง เช่น Ackermann function และ Tower of Hanoi เป็นต้น

Functions with Variable Argument Lists

ในบางครั้ง ฟังก์ชันที่เราต้องการจะเขียนไม่มีรูปแบบพารามิเตอร์ที่ตายตัว อาจจะมี 2-3 พารามิเตอร์หรือเราไม่ทราบจำนวนที่แน่ชัดของพารามิเตอร์ ยกตัวอย่างเช่นฟังก์ชัน NSLog จะเห็นว่าจำนวนของพารามิเตอร์ไม่แน่นอน

การแก้ปัญหาวิธีการแรกที่สามารถทำได้ก็คือใช้ array เป็นพารามิเตอร์ นอกจากวิธีนี้ยังมีอีกหนึ่งวิธีนั่นก็คือการใช้ variable list  การประกาศให้ฟังก์ชันรับพารามิเตอร์แบบ variable list สามารถทำได้ด้วยการประกาศพารามิเตอร์ลำดับรองสุดท้ายให้เป็น int และตัวสุดท้ายให้แทนด้วย …  ( 3 จุด ) ดังเช่นตัวอย่าง

เราจะเขียนโปรแกรมหาค่าเฉลี่ยจากพารามิเตอร์ที่รับเข้ามา ซึ่งมีโค้ดดังนี้

Program 6.5
main.m

Program 6.5 Output
Average 6.20
จากโค้ดของฟังก์ชัน average เราเริ่มต้นด้วยการประกาศตัวแปรต่างๆพร้อมกับตัวแปร arguments ซึ่งเป็น va_list ( variable list ) ต่อมาบรรทัดที่ 11 เป็นการเก็บค่าพารามิเตอร์หลังจาก firstNum ที่เหลือทั้งหมดมาไว้ที่ตัวแปร arguments นั่นคือค่า 4, 6 , 7 , 9 และ -1 จากนั้นโปรแกรมก็จะเริ่มเข้าสู่ while loop ซึ่งในลูปนี้ เราจะเริ่มนำค่าพารามิเตอร์ที่ได้เก็บไว้ยังตัวแปร arguments ออกมาทีละค่าด้วยฟังก์ชัน va_arg โดยต้องระบุด้วยว่าพารามิเตอร์นั้นเป็นชนิดใด จากตัวอย่างของโปรแกรมค่าที่รับเข้ามาเป็น int ทั้งหมด ดังนั้นเราจึงกำหนดให้เป็น int เช่นกัน (ในกรณีที่พารามิเตอร์เป็นหลายชนิด เราต้องกำหนดชนิดของพารามิเตอร์ให้ถูกต้องด้วย) เนื่องจากเราไม่สามารถรู้ได้ว่าฟังชั่นมีพารามิเตอร์จำนวนเท่าใด ดังนั้นเราจึงกำหนดว่า เมื่อไหร่ก็ตามที่พารามิเตอร์มีค่าเป็น -1 ก็ให้หยุดการทำงานของลูปนั่นเอง

C Standard Library

โดยปกติแล้วไม่ว่าจะเขียนโปรแกรมด้วยภาษาใดๆก็ตาม มักจะมีฟังก์ชันมาตรฐานให้ใช้งานเสมอ ในภาษา C ก็มีฟังก์ชันต่างๆมากมายให้ใช้เช่นกัน เรียกว่า C Standard Library ซึ่งมีฟังก์ชันต่างๆมากมาย ไม่สามารถอธิบายได้หมด ฟังก์ชันที่ควรรู้เบื้องต้นได้แก่ ฟังก์ชันและมาโครที่เกี่ยวกับคณิตศาสตร์ เช่น
t

Program 6.6

main.m

Program 6.6 Output
cos 30 degree = 0.866025
sin 30 degree = 0.500000
tan 30 degree = 0.577350
exp(10) = 20.085537
log(8) = 2.079442
pow(10,2) = 100.000000
sqrt(10) = 3.162278
ceil(6.3) = 7.000000
floor(6.3) = 6.000000
fabs(-6.3) = 6.300000
INT_MAX = 2147483647
INT_MIN = -2147483648
UINT_MAX = 4294967295d
arc4random = 445927451
เราจะหยุดเรื่องของฟังก์ชันเอาไว้เท่านี้ก่อน เพราะยังมีเรื่องที่ต้องทำความเข้าใจเพิ่มเติมนั่นก็คือ pointer

Pointer

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

Pointer definition and initialization

การประกาศตัวแปรแบบ pointer นี้สามารถทำได้โดยการเพิ่มเครื่องหมาย * (ดอกจันทร์) ด้านหน้าของชื่อตัวแปร ดังเช่นตัวอย่าง

เริ่มคุ้นๆแล้วใช่ไหมว่าเคยเห็นการประกาศตัวแปรรูปแบบนี้ที่ไหนมาก่อน ถูกต้องแล้ว เราได้ประกาศใช้ตัวแปรแบบ pointer มาตั้งแต่บทแรกแล้ว นั่นก็คือ

รวมไปถึงการประกาศ instance ของ object ต่างๆ ก็ประกาศให้เป็นตัวแปรแบบ pointer ทั้งสิ้น

เมื่อเราประกาศตัวแปรแบบ pointer นี้แล้วสิ่งที่ต้องทำต่อมาก็คือการกำหนดค่า memory address ให้กับตัวแปร แต่เราไม่สามารถจะกำหนด memory address แบบตรงๆได้ ต้องใช้เครื่องหมาย & ( address operator ) ดังเช่นตัวอย่าง

โดยปกติแล้วเมื่อประกาศตัวแปรเช่น int หรือ double ตัวแปรเหล่านี้จะเก็บค่าโดยตรงหรือเรียกว่า directly references a value เป็นต้นว่าประกาศตัวแปร int x = 4 ก็คือการกำหนด x ให้เท่ากับค่า 4 โดยตรง แต่การกำหนดค่าให้กับตัวแปรแบบ pointer จะเป็นแบบ indirectly refrence a value คือไม่ได้ให้ค่ากับตัวแปรนั้นตรงๆแต่เป็นอ้างอิงไปยังที่อื่น เช่น xPtr = &x หมายถึงการกำหนดให้ xPrt เก็บค่าตำแหน่งของ x

t2

สมมติว่าตัวแปร x อยู่บนตำแหน่ง 0x0A0 ส่วน xPrt อยู่ตำแหน่ง 0x0A8 ดังตาราง จะเห็นว่าค่าที่ตัวแปร x เก็บไว้คือเลข 4 และตัวแปร xPrt เก็บค่า 0x0A0 ซึ่งเป็นตำแหน่งของ x นั่นเอง หรือพูดอีกอย่างว่า xPrt ชี้ไปยังตำแหน่งของตัวแปร x และการจะให้ pointer ชี้ไปยังตัวแปรใดๆ เราจำเป็นต้องประกาศ pointer ให้เป็นชนิดเดียวกับตัวแปรนั้น เช่น สมมติว่าตัวแปรนั้นเป็น int ก็ต้องประกาศ pointer ให้เป็น int เช่นกัน

ref

จากรูปเมื่อ xPrt ชี้ไปยังตำแหน่ง x ได้นั่นก็หมายถึงว่า ตัวแปร xPrt เปรียบเสมือนหนทางไปสู่ข้อมูลของตัวแปร x อีกทางหนึ่งได้เช่นกัน เราสามารถที่จะเข้าใช้ข้อมูลในตำแหน่งนั้นด้วยใช้เครื่องหมาย * นำหน้า pointer เพื่อเป็นการ derefence pointer ดังเช่นตัวอย่างโปรแกรมง่ายๆต่อไปนี้

Program 6.7
main.m

Program 6.6 Output

Address x = 0x7fff5fbff89c
Value x = 10
Address xPtr = 0x7fff5fbff890
Value xPtr = 0x7fff5fbff89c
New Value x = 20

โปรแกรมได้กำหนดค่า x เท่ากับ 10 และ xPtr ให้ชี้ไปยังตำแหน่ง x จากนั้นก็แสดงค่า memory adress และค่าที่เก็บไว้ทั้งตัวแปร x และ xPrt ซึ่งจะเห็นว่าค่า Value xPrt นั้นเท่ากับค่า Address x และเมื่อโปรแกรมทำงานมาถึงบรรทัดที่ 18 เราได้ใช้เครื่องหมาย * เพื่อเป็นการ derefence pointer หรือการเข้าถึงค่าที่ xPrt ได้ชี้ไป นั่นก็ตำแหน่งของตัวแปร x หรืออาจจะพูดง่ายๆว่าเราได้กำหนดตัวแปร x ให้มีค่าเท่ากับ 20 นั่นเอง

Function and Pointer

จากโปรแกรม 6.4 เมื่อฟังก์ชัน factorial ถูกเรียกใช้งาน ค่าตัวแปรที่จากผู้เรียกฟังก์ชัน ( ตัวแปร num ใน main ) จะถูกคัดลอกไปยังตัวแปรที่เป็นพารามิเตอร์ของฟังก์ชัน ( ตัวแปร n ของฟังก์ชัน factorial ) นั่นหมาย num และ n เป็นคนละตัวแปรกัน ถ้าเราแก้ไขค่า n ก็จะไม่เกี่ยวกับค่า num เลย ตัวอย่างโปรแกรมง่ายๆต่อไปนี้ แสดงให้เห็นว่าค่า x ทั้งสองเป็นคนละตัวแปรกัน

Program Output

x mul: 20
x main: 10

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

Program 6.8
main.m

Program 6.8 Output

a = 10 , b = 30
a = 30 , b = 10

จากโปรแกรม 6.8 เราได้ส่งค่า &a และ &b ซึ่งหมายถึง memory address ของ a และ b ให้กับฟังก์ชัน swap ซึ่งรับพารามิเตอร์เป็น pointer ดังนั้นแล้วฟังก์ชันก็สามารถที่จะเข้าถึงตัวแปร a และ b ใน main ได้โดยตรง หลังจากฟังก์ชันสลับค่าระหว่างตัวแปรแล้ว เมื่อใช้ NSLog เพื่อแสดงผลลัพธ์ก็จะเห็นว่าค่า a และ b ได้สลับกัน ในบทต่อไปเมธอดของคลาสที่เราจะได้เขียนก็จะมีพารามิเตอร์เป็น pointer ลักษณะเช่นเดียวกัน หรืออย่างเมธอดของคลาสในบทที่ผ่านมาเช่น

ก็จะเห็นว่าฟังก์ชัน sampleObject ส่งค่ากลับมาเป็น pointer หรือ NSObject* และค่าที่ส่งกลับเป็นตำแหน่งของอ็อบเจ็กที่ได้สร้างขึ้นมาในฟังก์ชั่นนั่นเอง

Pointer and Object

มาถึงตรงนี้อาจจะสงสัยว่าเมื่อเราประกาศ instance ของ class อย่าง

แต่เรากลับไม่เห็นเครื่องหมาย & นั่นก็เพราะว่า เมธอด alloc นั้นจะส่งค่ากลับมาเป็นตำแหน่งหน่วยความจำที่ได้จากการสร้าง อ็อบเจ็กอยู่แล้ว ดังนั้นจึงไม่จำเป็นต้องใช้ & นั่นเองนำหน้านั่นเอง
ref2

เมื่อเขียนแผนภาพแสดงข้อมูลของตัวแปรจะเห็นว่าในความเป็นจริงแล้ว ตัวแปร manee นั้นไม่ได้เก็บค่า Student โดยตรง แต่เป็นตัวชี้ไปยังตำแหน่งหน่วยความจำที่เก็บค่า Student อีกที และหากเราสังเกตดูจะพบว่าเมธอดและฟังก์ชันที่มีพารามิเตอร์เป็นอ็อบเจ็กนั้นประกาศเป็นแบบ pointer ทั้งหมดนั่นก็เพราะว่า เมื่อโปรแกรมเรียกฟังก์ชันหรือเมธอด จะสร้างสิ่งที่เรียกว่า Frame ซึ่งเป็นข้อมูลที่ประกอบไปด้วย ตำแหน่งที่ต้องส่งค่ากลับ ตำแหน่งของโปรแกรมที่ต้องกลับไปเมื่อทำงานเสร็จ พารามิเตอร์ต่างๆที่ฟังก์ชันต้องการใช้งานและค่าอื่นๆ หลังจากสร้างเฟรมเสร็จก็จะถูกใส่เข้ามายัง Stack Frame เพื่อทำการประมวลผล และ Stack Frame นี้มีการทำงานในลักษณะเข้าก่อนออกทีหลัง เช่น factorial(5) ถูกเรียกก่อน แต่จะทำงานเสร็จทีหลัง factorial(0) ดังรูป

stack

เนื่องจาก Stack Frame นั้นมีจำกัด สิ่งที่เกิดขึ้นตามมาถ้าหากเราเขียนโปรแกรมได้ไม่ดีนั่นก็คือ Stack Frame เต็มหรือเรียกว่า Stack Overflow นั่นเอง นอกจากนี้ในการดีบักโปรแกรมคำที่จะคุ้นหูกันมากก็คือ call stack, stack trace ซึ่งหมายถึงการติดตามว่าตอนนี้ Stack Frame มีฟังก์ชันหรือเมธอดได้ทำงานนั่นเอง
ในการสร้างเฟรมนั้นค่าของตัวแปรที่เป็นพารามิเตอร์จะถูกคัดลอกไปยังตัวแปรในเฟรม ซึ่งนั่นหมายความว่ายิ่งมีพารามิเตอร์มากและขนาดใหญ่เท่าไหร่ Stack Frame ก็จะใหญ่ขึ้นไปด้วย ขนาดของ Stack Frame ส่งผลกระทบโดยตรงกับประสิทธิภาพของโปรแกรม ถึงแม้เราจะมี ram ขนาดหลาย GB. แต่ Stack Frame มันมีจำกัด นั่นก็เพราะว่าอันที่จริงแล้วหน่วยความจำในระบบคอมพิวเตอร์นั้นถูกแบ่งออกเป็นหลายระดับ โดยทั่วๆไปจะมีทั้งหมด 3 ระดับนั่นก็คือ register ซึ่งเป็นหน่วยความจำที่มาพร้อมกับ cpu ทำงานด้วยความเร็วเท่ากับ cpu แต่มีขนาดเล็กมากๆอย่าง cpu x86-64 bit ก็มีรีจิสเตอร์ 16 ตัวเท่านั้น ลำดับต่อมาคือ cpu cache เป็นหน่วยความจำที่อยู่ภายใน cpu เช่นเดียวกัน ทำงานช้ากว่า register  แต่มีขนาดใหญ่กว่า register อย่าง intel i7 ก็มีขนาดประมาณ 4-8 MB. และสุดท้ายคือ ram ซึ่งเป็นหน่วยความจำภายนอก cpu มีขนาดใหญ่ๆมาก และทำงานได้ช้ากว่า cache ถ้าเทียบความเร็วระหว่าง register , cache , ram ให้พอเห็นภาพง่ายๆก็คือ สมมติว่า register ทำงานเสร็จภายใน 1 วินาที แคชจะใช้เวลา 100 วินาที ส่วนแรมจะใช้เวลา 1000  วินาที ดังนั้นแล้วถ้าหากเราอยากจะให้โปรแกรมทำงานได้เร็วๆก็ต้องเอาโหลดโปรแกรมไปไว้ที่ register หรือ cache แต่ก็อย่างที่ทราบกันไปว่า cache มีขนาดจำกัดมากๆ จะเอาทั้งโปรแกรมไปไว้ก็ไม่ได้ ระบบคอมพิวเตอร์จึงออกแบบให้บางส่วนของโปรแกรมเช่น Stack Frame ไปไว้ในหน่วยความจำภายใน cpu และเพื่อลดขนาดของ stack frame เราจึงต้องเอาตัวแปรที่เป็นตัวชี้ไปยังตำแหน่งหน่วยความจำเช่น ram ไปไว้ที่ frame เพื่อที่ว่าเวลาที่จำเป็นต้องใช้ object นั้นจริงๆถึงจะไปโหลดจาก ram อีกครั้ง แบบนี้ประสิทธิภาพโดยรวมของโปรแกรมก็จะทำงานได้เร็วขึ้นนั่นเอง

โหลด PDF Chapter 6

Source code

One thought on “Objective-C Programming Chapter 6”

Leave a Reply