Showing posts with label inout mode. Show all posts
Showing posts with label inout mode. Show all posts

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 หรือไม่ ?