การกำหนดค่า

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

**สัญกรณ์**
ตัวแทนการนำเสนอแบบข้อความโดยสามัญของการกำหนดค่ามักจะใช้เครื่องหมายเท่ากับ "=" และ ":=" รูปแบบทั้งสองนี้เป็นรูปแบบปกติของภาษาโปรแกรมหลายภาษา (เช่นภาษาซี) ซึ่งจัดจำแนกการกำหนดค่าว่าเป็นตัวดำเนินการเติมกลาง
ความเป็นไปได้อย่างอื่นคือเพิ่มลูกศรชี้ข้างซ้ายหรือคำหลักเข้าไป หรือแม้แต่รูปแบบต่างที่สามารถใช้ได้ซึ่งพบเห็นได้น้อยกว่า
บางแพลตฟอร์มก็วางนิพจน์ไว้ทางซ้ายและวางตัวแปรไว้ทางขวา
ในภาษาโปรแกรมเชิงนิพจน์บางภาษา อย่างเช่นภาษาลิสป์  และภาษาทีซีแอล ใช้วากยสัมพันธ์แบบเติมหน้าเพียงอย่างเดียวสำหรับทุกข้อความสั่ง ซึ่งรวมทั้งการกำหนดค่าด้วย

**การดำเนินการ**
การดำเนินการกำหนดค่าตามความหมายแล้วเป็นการเปลี่ยนแปลงสถานะปัจจุบันของโปรแกรมที่กำลังทำงานอยู่ ดังนั้นการกำหนดค่าจึงขึ้นอยู่กับแนวคิดของตัวแปร ในการกำหนดค่าหนึ่ง ๆ นิพจน์ จะถูกประเมินค่าในสถานะปัจจุบันของโปรแกรม และ ตัวแปร จะถูกกำหนดด้วยค่าที่ประเมินนั้น แทนที่ค่าที่มีอยู่ก่อนหน้าในตัวแปร ตัวอย่างเช่น สมมติให้ a เป็นตัวแปรเชิงตัวเลข การกำหนดค่า a := 2*a หมายถึงการทำให้ข้อมูลของตัวแปร a เพิ่มค่าเป็นสองเท่าหลังจากทำงานข้อความสั่งนี้แล้ว
ต่อไปนี้คือตัวอย่างส่วนหนึ่งของภาษาซี
int x = 10;
float y;
x = 23;
y = 32.4;
จากตัวอย่างนี้ ตัวแปร x ประกาศไว้ว่าเป็นจำนวนเต็ม (int) เมื่อเริ่มแรก จากนั้นจึงกำหนดค่าเป็น 10 สังเกตว่าการประกาศและการกำหนดค่าเกิดขึ้นในข้อความสั่งเดียวกัน บรรทัดที่สอง ตัวแปร y ประกาศเป็นจำนวนจุดลอยตัว (float) โดยไม่กำหนดค่า บรรทัดถัดไป x ถูกกำหนดค่าใหม่ให้เป็น 23 และท้ายสุด y ถูกกำหนดให้มีค่าเท่ากับ 32.4
ในการดำเนินการกำหนดค่านั้น สิ่งสำคัญคือค่าของ นิพจน์ จะต้องนิยามไว้แล้วเป็นอย่างดี (เป็น rvalue ที่ถูกต้อง) และ ตัวแปร จะต้องแทนด้วยเอนทิตีที่สามารถแก้ไขได้ (เป็น lvalue ที่เปลี่ยนแปลงได้ คือไม่เป็นค่าคงตัว) ในบางภาษาอย่างเช่นภาษาเพิร์ล ไม่จำเป็นต้องประกาศตัวแปรก่อนกำหนดค่าก็ได้

**การกำหนดค่าแบบขนาน**
ภาษาโปรแกรมบางภาษาเช่น ภาษาอ็อกแคม 2
ภาษาไพทอน
ภาษาเพิร์ล
ภาษาเรบัล ภาษารูบี
วินโดวส์ เพาเวอร์เชลล์ และจาวาสคริปต์ (ตั้งแต่รุ่น 1.7) อนุญาตให้กำหนดค่าตัวแปรหลายตัวแบบขนานได้ (parallel assignment) ด้วยวากยสัมพันธ์คล้ายดังนี้
a,b := 0,1
คำสั่งนี้กำหนดค่า 0 ลงใน a และค่า 1 ลงใน b ในเวลาเดียวกัน ถ้าฝั่งขวามือของการกำหนดค่าเป็นตัวแปรแถวลำดับ คุณลักษณะดังนี้อาจเรียกว่า การขยายลำดับออก (sequence unpacking)
var list := 0,1
a,b := list
รายการแถวลำดับจะถูกขยายออก ทำให้กำหนดค่า 0 ลงใน a และค่า 1 ลงใน b ได้เช่นกัน รหัสต่อไปนี้เป็นตัวอย่างที่น่าสนใจ
a,b := b,a
ข้อความสั่งดังกล่าวจะสลับค่าของ a กับ b ส่วนภาษาที่ไม่มีการกำหนดค่าแบบขนาน การสลับค่าอาจต้องเขียนโดยใช้ตัวแปรชั่วคราว t ดังนี้
var t := a
a := b
b := t
เนื่องจากข้อความสั่ง a:=b ; b:=a จะส่งผลให้ตัวแปรทั้งสองมีค่าเดียวกันคือค่าเริ่มต้นของ b
การกำหนดค่าแบบขนานเริ่มแนะนำในภาษาซีพีแอลเมื่อ พ.ศ. 2506 (ค.ศ. 1963) ในชื่อ การกำหนดค่าพร้อมกัน (simultaneous assignment) 

**ค่าของการกำหนดค่า**
ในภาษาโปรแกรมเชิงนิพจน์ส่วนใหญ่ ข้อความสั่งกำหนดค่าจะคืนค่าเป็นค่าที่ถูกกำหนดนั้น ซึ่งทำให้ข้อความสั่งเช่น x = y = a ค่าของ a จะถูกกำหนดให้กับทั้ง x และ y หรืออย่างเช่น while (f = read()) {…} ค่าที่คืนจากฟังก์ชันจะเป็นตัวควบคุมการวนรอบ ในเวลาเดียวกันก็กำหนดค่าที่เหมือนกันให้กับตัวแปรด้วย
ส่วนภาษาโปรแกรมอื่น ค่าที่ส่งคืนจากการกำหนดค่าอาจไม่นิยาม และทำให้ข้อความสั่งเช่นนั้นใช้การไม่ได้ ยกตัวอย่างเช่นภาษาสกีม
ภาษาไพทอนถือว่าการกำหนดค่าไม่ใช่นิพจน์ ดังนั้นมันจึงไม่มีค่าใด ๆ ส่งคืนกลับมา
ในภาษาแฮสเกลล์  ไม่มีการกำหนดค่าให้กับตัวแปร แต่การดำเนินการที่คล้ายกับการกำหนดค่า (เหมือนการกำหนดค่าไปยังเขตข้อมูลของแถวลำดับ หรือเขตข้อมูลของโครงสร้างข้อมูลเปลี่ยนแปลงได้) คือการประเมินค่าเป็นยูนิต ซึ่งเป็นชนิดข้อมูลทั่วไปของนิพจน์ที่ถูกประเมินค่าเพื่อให้เกิดผลข้างเคียงโดยเฉพาะ

**การกำหนดค่าปกติกับการกำหนดค่าเชิงเดี่ยว**
ในการเขียนโปรแกรมเชิงฟังก์ชัน การกำหนดค่าจะลดความสำคัญลงเพื่อประโยชน์ในการกำหนดค่าเชิงเดี่ยว (single assignment) หรืออาจเรียกว่า การยึดเหนี่ยวกับชื่อ หรือ การกำหนดค่าเริ่มต้น การกำหนดค่าเชิงเดี่ยวต่างจากการกำหนดค่าปกติตรงที่สามารถกำหนดค่าได้เพียงครั้งเดียวเท่านั้น โดยเฉพาะเมื่อตัวแปรถูกสร้างขึ้น นั่นคือไม่สามารถกำหนดค่าใหม่ภายหลัง ค่าที่ถูกตั้งชื่อโดยการกำหนดค่าเชิงเดี่ยวจะไม่ถือว่าเป็นตัวแปร แต่จะเป็นวัตถุเปลี่ยนแปลงไม่ได้
การกำหนดค่าเชิงเดี่ยวเป็นรูปแบบเพียงอย่างเดียวที่มีอยู่สำหรับภาษาโปรแกรมเชิงฟังก์ชันอย่างแท้จริง (purely funtional) เช่นภาษาแฮสเกลล์ ซึ่งไม่มีตัวแปรอย่างภาษาโปรแกรมเชิงคำสั่งอื่น ๆ ภาษาโปรแกรมเชิงฟังก์ชันที่ไม่แท้จริงก็อาจมีทั้งการกำหนดค่าเชิงเดี่ยวและการกำหนดค่าปกติ (แม้ว่าการกำหนดค่าปกติมีที่ใช้น้อยกว่าในภาษาโปรแกรมเชิงคำสั่ง) ตัวอย่างเช่น ในภาษาสกีม การกำหนดค่าเชิงเดี่ยวและการกำหนดค่าปกติสามารถใช้ได้กับตัวแปรทุกตัว หรือในภาษาอ็อบเจกทีฟแคมัล การกำหนดค่าเชิงเดี่ยวใช้กับตัวแปรโดยใช้รูปแบบ let ชื่อ = ค่า ส่วนการกำหนดค่าปกติซึ่งใช้ตัวดำเนินการ  ใช้กับสมาชิกของแถวลำดับและสายอักขระ เช่นเดียวกับเขตข้อมูลของระเบียนและวัตถุที่ถูกประกาศอย่างชัดเจนว่าให้สามารถเปลี่ยนแปลงได้ (หมายความว่าขนาดความจุของมันสามารถเปลี่ยนแปลงได้หลังจากการประกาศตอนเริ่มต้น)

**การกำหนดค่าและภาวะเท่ากัน**
โปรแกรมเมอร์ ระดับเริ่มต้นเกิดความสับสนบ่อยครั้งระหว่างการกำหนดค่ากับตัวดำเนินการสัมพันธ์ของภาวะเท่ากัน เนื่องจาก = หมายถึงภาวะเท่ากันในทางคณิตศาสตร์ และถูกใช้เป็นตัวดำเนินการกำหนดค่าในหลายภาษา แต่การกำหนดค่าคือการเปลี่ยนแปลงค่าของตัวแปร ในขณะที่การทดสอบภาวะเท่ากันจะตรวจสอบนิพจน์สองนิพจน์ว่ามีค่าเหมือนกันหรือไม่
หลายภาษาใช้สัญกรณ์ที่แตกต่างกันสำหรับการดำเนินการแต่ละชนิด ตัวอย่างเช่น ตัวดำเนินการกำหนดค่าใช้เครื่องหมายเท่ากับตัวเดียว = ในขณะที่ตัวดำเนินการเทียบเท่าใช้เครื่องหมายเท่ากับสองตัว == ในภาษาซี แต่ในบางภาษาเช่นภาษาเบสิก เครื่องหมายเท่ากับตัวเดียวใช้แทนการดำเนินการทั้งสอง ซึ่งความหมายของมันจะพิจารณาจากบริบท
ความสับสนเช่นนี้อาจนำไปสู่ความผิดพลาด หากโปรแกรมเมอร์หลงลืมว่ารูปแบบใดถูกต้องเหมาะสม หรือลงรหัสผิดพลาด (เช่นพิมพ์ = แทนที่ตั้งใจให้เป็น ==) เป็นปัญหาปกติสามัญของการเขียนโปรแกรม อาทิในภาษาซี ตัวดำเนินการกำหนดค่าจะคืนค่าเป็นค่าที่กำหนดไปนั้น และสามารถใช้ซ้อนภายในนิพจน์ได้ (แบบเดียวกับฟังก์ชันที่คืนค่าออกมา) ถ้าความตั้งใจคือการเปรียบเทียบค่าสองค่าในเงื่อนไข if การกำหนดค่าในเงื่อนไขอาจถูกตีความหมายว่าเป็นค่า TRUE ซึ่งจะทำให้ข้อความสั่งตามเงื่อนไขทำงาน นำไปสู่พฤติกรรมของโปรแกรมที่ไม่คาดหวัง ตัวประมวลผลของบางภาษาสามารถตรวจจับสถานการณ์เช่นนั้น และแจ้งเตือนโปรแกรมเมอร์เกี่ยวกับความผิดพลาดที่อาจเกิดขึ้นได้

**อ้างอิง**

**ดูเพิ่ม**
 การยึดเหนี่ยวกับชื่อ- การรวมเป็นหนึ่ง
หมวดหมู่:มโนทัศน์ภาษาโปรแกรม