Thursday, July 16, 2015

Parameter passing mode

Parameter Passing Mode 
โหมดการส่งผ่านค่าสู่พารามิเตอร์ (Parameter passing mode)  ในการเขียนโปรแกรมภาษาใดๆก็ตาม เมื่อมีการสร้างฟังก์ชั่น ก็มักจะมีการส่งผ่านค่าเข้าสู่พารามิเตอร์ของฟังก์ชั่น  การส่งผ่านค่านั้นโดยพื้นฐานจะมี 3 ลักษณะหรือโหมดการทำงานในการส่งผ่านค่าสู่พารามิเตอร์
1. in mode พารามิเตอร์ของฟังก์ชั่นรับค่าเข้าเพียงอย่างเดียว
2. out mode พารามิเตอร์ของฟังก์ชั่นไม่รับค่าเข้าแต่มีการส่งค่ากลับไปยังเออร์กูเมนต์ (ตัวแปรที่ส่งค่ามายังพารามิเตอร์ของฟังก์ชั่น)
3. inout mode พารามิเตอร์ของฟังก์ชั่นรับค่าเข้าและส่งค่ากลับไปยังเออร์กูเมนต์

ฟังก์ชั่นหนึ่งๆ  อาจมีหลายพารามิเตอร์ และแต่ละพารามิเตอร์อาจทำงานด้วยโหมดที่แตกต่างกันก็ได้
ภาษาการโปรแกรมหนึ่งๆ เลือกออกแบบโหมดในการส่งผ่านค่าสู่พารามิเตอร์ที่แตกต่างกัน   โหมดที่สร้างปัญหาได้มากที่สุดคือโหมด  inout mode จะได้ยกตัวอย่างต่อไป
ที่บรรยายมานี้ยังไม่เกี่ยวข้องกับการส่งพารามิเตอร์  Passing by value, Passing by reference ขออธิบายการทำงานของพารามิเตอร์ในแต่ละโหมดก่อน


ในหลักการการโปรแกรม  Actual parameter คือค่าจริงที่จะถูกส่งให้กับพารามิเตอร์ในฟังก์ชั่น หรือ Formal parameter  ซึ่ง Formal parameter พารามิเตอร์ที่ประกาศในฟังก์ชัน
ภาษาการโปรแกรมอาจสนับสนุนทั้ง 3 โหมด

int a = 5, b = 10, c = 15;
myfunction(a, b, &c);
....
void myfunction(int x, int y, int *z){
                x = x +10;                 
                y = y + 5;
              *z = *z + 20;
    printf("%d  %d  %d", x, y, *z);
}

จากโค้ดด้านบนพารามิเตอร์ x และ y ทำงานในโหมด in mode ส่วน z ทำงานในโหมด inout mode เพราะการแก้ไขค่าที่พอยน์เตอร์ z ชี้อยู่จะถูกนำไปสำเนาให้กับ Actual parameter c ซึ่งมีค่าเท่ากับ 35 ส่วน a และ b ยังคงมีค่าเท่ากับ 5 และ 10 ตามลำดับ
สมมติให้โค้ดมาตามนี้

int a = 10, b = 20;
myanotherfunc(&a, &a);
....
void myfunction(int *x, int *y){
              *x = *x +10;                 
               *y = *y + 5;
     printf("%d  %d  ", x, y);


}


จะเห็นว่า  Actual parameter คือ a ส่วน Formal parameter คือพอยน์เตอร์ x และ y ซึ่งชี้ไปยังตำแหน่งในเมมโมรีตำแหน่งเดียวกัน  และ Formal parameter  x และ y ทำงานใน inout mode ซึ่งจะรับค่าเข้าและส่งกลับ 
คำถามคือถ้าหากมีการส่ง Actual parameter เข้าสู่ฟังก์ชั่น ผลลัพธ์ที่จะถูกส่งกลับคืออะไร  ?
หากโปรแกรมเมอร์พิจารณาดูตามโค้ด  ก็อาจจะตอบว่า   20 หรือ 15     

พิจารณาการใช้งานเมมโมรีกับพอยน์เตอร์  พารามิเตอร์ในฟังก์ชั่นจะถูกจองพื้นที่ในส่วนของ x และ y แต่สำเนาค่าจากตำแหน่งของตัวแปร a ซึ่งมีค่าเท่ากับ 10  (ภาพบน)  ถ้าการจับคู่ของ Actual และ Formal parameter จากซ้ายไปขวา (ภาพบนซ้าย) พารามิเตอร์ y จะอยู่ top of stack แล้วเมื่อมีการส่งค่ากลับหลังจากประเมินผลนิพจน์  ค่าของพารามิเตอร์ x จะถูกส่งไปทีหลัง  ซึ่งจะทำให้ a มีค่าเท่ากับ 20 
ในทางกลับกัน ถ้าการจับคู่ทำจากขวาไปซ้าย  พารามิเตอร์ x จะอยู่ top of stack   แล้ว a จะมีค่าเป็น 15 เนื่องจากพารามิเตอร์ y จะถูกส่งไปทีหลัง (ภาพบนขวา) 

   

ในภาษาการโปรแกรมที่มีการออกแบบ   จะกำหนดลักษณะการส่งค่าเออร์กูเมนต์สู่พารามิเตอร์  เป็นลักษณะต่างๆ  เช่น 
  1. Pass-by-value มีการทำสำเนาค่าของ Actual parameter ให้กับ Formal parameter หรือเป็นการส่งค่าแบบ  in mode
  2. Pass-by-result ไม่มีการสำเนาค่าของ Actual parameter ให้กับ Formal parameter แต่มีการรีเทิร์นค่ากลับจาก Formal parameter ให้กับ Actual parameter หรือเป็นการส่งค่าแบบ out mode การส่งลักษณะนี้มีในภาษา C#
  3. Pass-by-value-result มีการทำสำเนาค่าจาก Actual parameter ให้กับ Formal parameter และมีการส่งค่ากลับจาก Formal parameter ให้กับ Actual parameter หรือเป็นการส่งในลักษณะ  inout mode (ดังตัวอย่างด้านบน)
  4. Pass-by-reference ไม่มีการสำเนาค่าของ Actual parameter ให้กับ Formal parameter แต่ส่ง Access path (ตำแหน่งของ Actual) ให้กับ Formal parameter  ซึ่งจะเกิดปัญหา Aliasing เมื่อระหว่างการทำงานภายในฟังก์ชั่นมีการอ้างอิง Nonlocal variable (ตัวแปรที่อยู่นอกฟังก์ชั่น) ในภาษา C++ มีการใช้งานในลักษณะนี้ เช่น  void fun(int &first, int &second) เป็นการประกาศพารามิเตอร์ในลักษณะ inout mode ซึ่งสามารถเรียกฟังก์ชั่นเช่น fun (a, b) ซึ่งตัวแปร first และ second จะอ้างอิงตำแหน่งในเมมโมรีของ a และ b โดยไม่มีการสำเนาค่าไว้ในเมมโมรีของฟังก์ชั่น
  5. Pass-by-name มีการส่งผ่านค่าในลักษณะ inout mode แต่ไม่เกี่ยวข้องกับลำดับการจับคู่ของ Actual parameter และ Formal parameter ขึ้นกับการ execute นิพจน์ในฟังก์ชั่น  การทำงานในลักษณะนี้มีภาษาการโปรแกรมไม่มากนักที่สนับสนุน


โดยสรุป
ในการใช้งาน inout parameter passing mode นั้น จำเป็นที่จะต้องพิจารณาลำดับในการเข้าคู่ของ Actual parameter และ Formal parameter เนื่องจากจะสัมพันธ์กับการรีเทิร์นค่ากลับ ซึ่งการรีเทิร์นค่ากลับนั้นพิจารณาจาก Stack ของ function

แบบฝึกหัด
1. ถ้ากำหนดการส่งค่าเข้าสู่ฟังก์ชั่น
fun(list[i], list[j])
void fun(int &first, int &second){
..
}
เป็นแบบ Pass-by-reference โดย i และ j มีค่าเท่ากัน  จะเกิดปัญหา Aliasing หรือไม่?
2.  ถ้ากำหนด
fun1(list[i], list)
void fun(int &first, int &second){
..
}
first และ second จะเป็น Alias หรือไม่ ?

3 comments:

  1. ตามหาความรู้เกี่ยวกับ programing language ภาษาไทยมานาน ขอบคุณมากๆครับ สำหรับความรู้ เป็นแรงใจให้ครับ

    ReplyDelete
  2. ตามหาความรู้เกี่ยวกับ programing language ภาษาไทยมานาน ขอบคุณมากๆครับ สำหรับความรู้ เป็นแรงใจให้ครับ

    ReplyDelete
  3. ไม่นึกว่าจะมีคนอ่าน ถูกผิดบอกได้นะคะส่วนใหญ่มาจาก Robesta ขอบคุณค่ะ

    ReplyDelete