Pointer กับตัวแปร Array นะจ๊ะ.. [Back to basic แต่ไม่ basic]


     บทความเกิดเพราะเร็ว ๆ นี้เจ้าของบล็อกกำลังจะสอนน้องพอดี วันนี้ก็เลยกลับไป Back to basic อีกครั้ง แต่เพราะกลับมา Back to basic นี่แหละ ทำให้เจ้าของบล็อกเข้าใจในเรื่อง Pointer ขึ้นอีกนิดนึง ก็เลยจะเอามาแชร์กัน


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

  

    
     ถ้ามีน้องกำลังอ่านอยู่ก็อย่าพึ่งกลัวละกันนะ (ฮ่า ๆ) จริง ๆ บทความนี้จะเน้นไปที่ Pointer มากกว่า การที่มาอธิบายเรื่อง Array ก่อนถือว่าปูพื้นก่อนจะได้เข้าใจมากขึ้น

     จากรูปถ้าสังเกตุนะ ค่า Address ของแต่ละ Index ใน Array จะห่างกันที่ 4 Byte (ค่า Address ที่เจ้าของบล็อกเขียนไปให้อ่านในรูปแบบ Byte นะ)

      ต่อมานะ เจ้าของบล็อกจะกำหนดค่าเข้าไปใน Array โดยการวน loop for กัน ดูจากโค้ดตัวอย่างได้เลยจ่ะ


     และในตอนนี้ค่าที่อยู่ใน Array ก็จะได้ประมาณนี้ออกมา

  
      หมดละเรื่องจะสอนสำหรับ Array (ฮ่า ๆ จะกระทืบเจ้าขอล็อกมั้ยเนี่ย)

เป้าหมายในการเขียนเรื่อง Array ก่อนเพื่ออยากให้ผู้อ่านได้รู้ว่า
  • ตัวแปรในแต่ละช่องของ Array มี Address ที่ต่อกัน
  • การอ้างถึงตัวแปรแต่ละช่องใน Array จะใช้ค่า Index เช่น arrayNumber[0] ก็คือใช้ Array ช่องที่ 0
  • การเข้าถึงตัวแปรในแต่ละ Index ใช้เครื่องหมาย [] (bracket) ถึงในตัวอย่างจะไม่ได้สอนแต่ก็มีตัวอย่างให้ดู

 
      เมื่อพูดเรื่อง Array คร่าว ๆ กันไปแล้ว ก็ยินดีเข้าสู่เนื้อหา Pointer กับตัวแปร Array กันซักที.. สวัสดีเรา Pointer จ้าวปัญหาไงละ จำเราได้เปล่า เดี๋ยว ๆ ผิด ๆ ฮ่า ๆ อยากจะบอกว่าจริง ๆ ไม่ได้น่ากลัวขนาดนั้นหรอกนะ

     เมื่อพูดถึงเรื่อง Pointer จากนิยามตามหนังสือต่าง ๆ Pointer ก็คือตัวชี้ ถูกต้องมั้ย ชี้อะไรน่ะหรอ.. ก็ชี้ Address ของตัวแปรไง หน้าที่มันก็มีแค่นี้แหละ ถึงจะบอกว่าหน้าที่มันมีแค่นี้ แต่มันก็เป็นจุดเด่นของภาษา C/C++ เหมือนกันนะ

     มาเริ่ม ๆ ออกทะเลละ


      นี่คือหน้าตาของ Pointer (น่ารักใช่มั้ยละ -//-) ประกาศเหมือนตัวแปรทั่วไปเลย คือมีชนิดตัวแปรและก็ชื่อของตัวแปร แต่มีสิ่งหนึ่งที่เพิ่มขึ้นมาจนเป็นเอกลักษณ์ของ Pointer เลยก็คือ * (star) เป็นสิ่งที่ทำให้มันพิเศษกว่าตัวแปรอื่นยังไงละ

     ในส่วนการใช้งานตัวแปร Pointer ต้องเข้าใจก่อนว่า Pointer นั้นเป็นตัวแปรที่เก็บค่า Address ดังนั้นการกำหนดค่าให้กับตัวแปร Pointer จะมีลักษณะที่คล้าย ๆ กัน ก็คือชี้ไปที่ Address ตัวอื่น ๆ 


    จะสังเกตุว่าการกำหนดค่าหรือชี้ค่าของตัวแปร Pointer ไปที่ Address ของตัวแปรตัวอื่น จะไม่ใช้ * (star)  ถ้าจะให้เข้าใจจริง ๆ เราต้องมาไล่กันดูทีละบรรทัดของโปรแกรม


     ถ้าเราสมมติว่ามันคือกล่อง ๆ นึง ในตอนแรกเราสร้างตัวแปร Pointer ขึ้นมาโดยที่ยังไม่ได้ให้มันชี้ค่าไปที่ไหนเลย กล่องใบนั้นจะมีเพียงชื่อ(ชื่อตัวแปร) และที่อยู่(Address) ตัวแปรทุกตัวจะมี Address กันหมดนะ ถึงจะเป็น Pointer ที่มีหน้าที่ชี้ไป Address ตัวอื่นก็เหอะ

     กล่องใบที่สองเราสร้างตัวแปร int ธรรมดา ๆ (ที่เธอไม่สนใจ.. เศร้า) ขึ้นมา แต่กล่องใบนี้ไม่เพียงแต่มีชื่อและที่อยู่เท่านั้น ยังมีสิ่งของที่อยู่ข้างในมันอีกด้วย ทำให้กล่องใบนี้มีค่าขึ้นมา(ถึงเธอจะไม่สนใจ แต่เราก็ยังมีค่านะ)

     และในท้ายที่สุดกล่องตัวที่สอง ก็ได้ตกหลุมรักกับกล่องใบแรก และสาบานไว้ว่าจะยกชีวิตให้กับกล่องใบแรก.. ตอนนี้หมายความว่า Pointer ชี้ไปที่ Address ของตัวแปร Integer เนื่องจากว่าถ้า Pointer มีค่าเป็น Address ของตัวแปรตัวแรกจะทำให้ตัวแปร Pointer นั้นสามารถเปลี่ยนแปลงค่าที่อยู่ใน Address ของตัวแปร Integer นั้นได้


     เมื่เราต้องการเปลี่ยนแปลงค่าที่อยู่ในตัวแปรที่เราชี้อยู่ เราจะใช้ * (star) ด้วย หลักง่าย ๆ ของ Pointer คือ ถ้าไม่มี *(star) จะเป็นการชี้ไปยัง Address ส่วนถ้ามี * (star) ก็คือ Pointer ต้องการเปลี่ยนแปลงค่าที่อยู่ในตัวแปรที่ Pointer ตัวนั้นชี้อยู่

     ในตอนนี้หลังจากที่กล่องใบที่สองสาบานว่าจะฝากชีิวิตไว้ที่กล่องใบแรก เจ้ากล่องใบแรกยังจะไปทำให้ชีวิตของกล่องใบที่ 2 แย่ลงอีก (จากเดิมที่มีค่า 100 เหลือ 50 จะสังเกตุว่าเจ้าของบล็อกไม่ได้ยุ่งเกี่ยวกับตัวแปร number อีกเลย ใช้แค่ตัวแปร pointer อย่างเดียว แต่ก็สามารถเปลี่ยนแปลงค่าที่อยู่ใน number ได้เช่นกัน)


      อยากบอกว่าที่อธิบายไปตะกี้ยังไม่เริ่มเนื้อหาจริง ๆ ของบทความนี้เลย อยากบอกว่าง่วงมาก นี่ก็เช้าละฮ่า ๆ แต่ไม่เป็นไร เปิด god mode ไปละ อยู่ได้อีก 30 นาที (นี่เปิดแล้วหรอ?)

      เวลาเราจะใช้ Pointer กับ Array เราจะทำอย่างไร


     อ้าวแล้วทำไมตอนนี้ชี้ไปที่ Address ของ array ถึงไม่มี & นำหน้าเหมือนตัวแปรก่อนหน้านี้แล้วละ? อาจจะมีผู้อ่านหลายท่านสงสัย แต่จริง ๆ แล้วการเขียนชื่อตัวแปรห้วน ๆ แบบในตัวอย่าง จริง ๆ มันคือการนำค่า Address ของ Array ช่องที่ 0 ออกมายังไงละ


      การเขียนแบบนี้ความหมายไม่ได้แตกต่างไปจากการเขียนก่อนหน้านี้ เพราะการเขียนทั้งสองแบบคือต้องการให้ตัวแปร Pointer ชี้ไปที่อยู่ตำแหน่งแรกของ Array เท่านั้น

     ต่อมาก็คือการใช้งานว่าเราจะให้ Pointer เปลี่ยนแปลงค่าใน Array ได้ยังไงกัน ซึ่งก็ไม่ได้ยากเย็นอะไรเลยเพราะสามารถเขียนแบบนี้ได้


     จะเห็นว่า ถึงแม้ว่าจะเป็นตัวแปร Pointer แต่เวลาเปลี่ยนแปลงค่าใน Array จะใช้วิธีการเหมือนกันกับตัวแปร Array เลย ที่ต้องอ้างอิงผ่าน Index ยังไงละ

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


      ก็เนื่องจากว่าเร็ว ๆ นี้จะสอนน้องอะแหละ วันนี้เลยลองเขียนตัวแปรประมาณนี้ 



     ผลลัพธ์ที่ได้



     แล้วมาดู address ของตัวแปรแต่ละตัว มันเรียงต่อกัน อ่าหะ ก็คงเป็นอย่างงั้นอยู่แล้ว แต่เอ๊ะ นึกขึ้นได้บางอย่าง address มันเรียงต่อกัน ก็คล้าย ๆ กับ array เลยอะดิ (นี่เป็นสาเหตุที่อยากให้ผู้อ่านที่อ่านมาถึงตรงนี้ เน้นกับค่า address ของตัวแปร array ที่เรียงต่อกันที่บอกไว้ข้างต้นก่อนหน้านี้) ก็เลยลองสร้างตัวแปร pointer ชี้ไปที่ d ดู (เพราะว่าค่า Address ของตัวแปร d น้อยสุด และ address ของ a มากสุดตามลำดับ) แล้วลองเขียนแบบนี้ไป
     (ptrD+1) ที่เห็นมัน +1 หรือ + 2 นี่ไม่ใช่อะไรนะ ความหมายเดียวกันกับ ptrD[1] กับ ptrD[2] นั่นแหละ แค่อยากให้เห็นว่ามันทำแบบนี้ก็ได้

นี่คือผลลัพ์ที่ได้จากการรันโปรแกรม


     ที่ต้องการอยากจะสื่อก็คือ Pointer มันสามารถ update ค่าตัวแปรเหล่านั้นแบบ array ได้ยังไงละ และถ้าผู้ใช้ไม่รู้ว่ามันทำอย่างนี้ได้ ก็อาจจะสร้างหายนะกับโปรแกรมได้เหมือนกัน

     ภาพรวมเรื่องที่อยากจะเขียนก็หมดแล้ว แต่ข้างล่างต่อไปนี้คือสาเหตุว่าทำไมมันถึงทำแบบนั้นได้

      อย่างที่บอกไป เมื่อเจ้าของบล็อกลองสร้างตัวแปร 4 ตัวนี้ขึ้นมา แล้วสังเกตว่า มันดันมีตำแหน่ง Address ต่อกัน มันทำให้นึกขึ้นได้ว่า Address มันเรียงต่อกันเหมือนกับ Array เลยนี่หว่า


     เลยลองทำกับตัวแปรให้เหมือนทำกับ Array เลยละกัน โดยให้ Pointer ชี้ไปยังที่ตำแหน่งแรกสุดของตัวแปร นั่นก็คือตัวแปร d ซึ่งค่า Address ของมันก็คือ 20 (ค่าสมมติ) จากนั้นก็เริ่มทำการเปลี่ยนแปลงค่าไปทีละ Address ซึ่งมันสามารถทำได้


     ถ้ายังจำได้ แบบไม่มี *(star) คือเกี่ยวกับการชี้ที่อยู่หรือ Address ส่วนถ้ามี *(star) คือต้องการเปลี่ยนแปลงค่าของ Address ที่เราชี้อยู่ ดังนั้นสมมติถ้าเจ้าของบล็อกต้องการจะเปลี่ยนแปลงค่าที่ Address ของตัวแปร c จะเขียนว่า


     ค่า c ก็จะเปลี่ยนเป็น 500 ทันที

     จบซักที ไม่รู้ว่าถ้าผู้อ่าน อ่านไปแล้วจะงงมั้ย ยังไง ช่วย feedback ด้วยนะครับ เพราะเจ้าของบล็อกเองก็ทั้งเขียนทั้งวาดรูป ง่วงก็ง่วง ฮ่า ๆ ๆ ตอนนี้ก็ 8 โมงแล้วครับ ขอตัวไปนอนก่อน เจอกันใหม่บทความของ ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม ตอนที่ 3 นะครับ เดี๋ยวจะเขียนต่อให้จบเร็ว ๆ นี้แหละ

ความคิดเห็น

Unknown กล่าวว่า
อธิบายได้เข้าใจได้ดีเลยครับ
Unknown กล่าวว่า
ขอบคุณครับผมพอเข้าใจขึื้นบางแล้วเดียวจะลองทบทวนดูอีกทีครับ

โพสต์ยอดนิยมจากบล็อกนี้

ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม : รู้จักกับ Memory

คณิตศาสตร์กับโปรแกรมมิ่งมันเป็นยังไงนะ ตอนที่ 1 เกริ่นพีทาโกรัส