ความใช้แทนกันได้ระหว่างตัวชี้และแถวลำดับ


คุณลักษณะเด่นชัดของภาษาซี (ซึ่งอาจทำให้สับสนด้วย) คือการปฏิบัติต่อแถวลำดับและตัวชี้ สัญกรณ์แถวลำดับ x[i] สามารถใช้กับตัวชี้ x ได้ โดยแปลความหมายว่าเป็นการเข้าถึงวัตถุตัวที่ i + 1 ของวัตถุข้อมูลที่อยู่ติดกันถัดจากตำแหน่งที่ x ชี้อยู่ ซึ่งถือว่าเป็นสมาชิกตัวแรกของแถวลำดับ (x[0])

x[i] มีความหมายเทียบเท่า *(x + i) ตามรูปแบบ และเนื่องจากชนิดตัวแปรของตัวชี้เป็นที่ทราบขณะแปล ตำแหน่ง x + i ที่ชี้ไปมิได้หมายความว่าจากตำแหน่ง x แล้วเพิ่มไปอีก i ไบต์ แต่หมายถึงเพิ่มไปอีก (i คูณด้วยขนาดของสมาชิกที่ตำแหน่ง x) ขนาดของสมาชิกนี้ได้มาจากการใช้ตัวดำเนินการ sizeof บนสมาชิกที่อ้างอิงกลับตัวใดตัวหนึ่งของ x ดังเช่น n = sizeof *x หรือ n = sizeof x[0]

นอกจากนี้ในบริบทส่วนใหญ่ของนิพจน์ ชื่อของแถวลำดับจะถูกแปลงเป็นตัวชี้ที่ชี้ไปยังสมาชิกตัวแรกของแถวลำดับนั้น สิ่งนี้บอกเป็นนัยว่าแถวลำดับจะไม่ถูกคัดลอกข้อมูลไปทั้งหมดเมื่อนำไปตั้งชื่ออาร์กิวเมนต์ของฟังก์ชัน แต่จะมีเพียงแค่ตำแหน่งของสมาชิกตัวแรกเท่านั้นที่ส่งผ่านไป ดังนั้นถึงแม้ว่าการเรียกใช้ฟังก์ชันในภาษาซีจะตีความว่าส่งโดยให้ค่า (pass-by-value) แต่แถวลำดับนั้นส่งโดยอ้างอิง (pass-by-reference) ในทางปฏิบัติ

จำนวนสมาชิกของแถวลำดับ x ที่ได้ประกาศไว้แล้ว สามารถคำนวณได้จาก sizeof x / sizeof x[0]

การสาธิตอย่างหนึ่งที่น่าสนใจต่อความใช้แทนกันได้ระหว่างตัวชี้และแถวลำดับแสดงไว้ด้านล่าง การกำหนดค่าทั้งสี่มีความหมายเทียบเท่ากันและเป็นรหัสที่ใช้งานได้ในภาษาซี

/* x เป็นแถวลำดับหรือตัวชี้, i เป็นจำนวนเต็ม */



x[i] = 1;         /* เทียบเท่ากับ *(x + i) */

*(x + i) = 1;

*(i + x) = 1;

i[x] = 1;         /* เทียบเท่ากับ *(i + x) */

แม้ว่าการกำหนดค่าทั้งสี่เทียบเท่ากัน แต่มีเพียงแบบแรกเท่านั้นที่แสดงรูปแบบการลงรหัสที่ดี กรณีอื่นอาจพบได้ในรหัสภาษาซีที่ยุ่งเหยิง

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

ไม่มีความคิดเห็น:

แสดงความคิดเห็น