การกำหนดค่า

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

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

 ตัวแปร = นิพจน์  ภาษาเบสิก, ภาษาฟอร์แทรน, ภาษาซี, ภาษาจาวา, ภาษาพีแอล/วัน, วินโดวส์ เพาเวอร์เชลล์, บอร์นเชลล์, ฯลฯ ตัวแปร := นิพจน์  ภาษาอัลกอล, ภาษาปาสกาล, ภาษาเอดา, ภาษาดิลัน, ภาษาไอเฟล, ฯลฯ

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

 ตัวแปร << นิพจน์  ภาษาแมจิก ตัวแปร <- นิพจน์  ภาษาอ็อบเจกทีฟแคมัล, ภาษาเอส, ภาษาอาร์, ฯลฯ ตัวแปร ← นิพจน์  ภาษาเอพีแอล ตัวแปร =: นิพจน์  ภาษาเจ LET ตัวแปร = นิพจน์  ภาษาเบสิก set ตัวแปร to นิพจน์  แอปเปิลสคริปต์ set ตัวแปร = นิพจน์  ซีเชลล์ Set-Variable ตัวแปร (นิพจน์)  วินโดวส์ เพาเวอร์เชลล์ val ตัวแปร = นิพจน์  ภาษาเอ็มแอล ตัวแปร : นิพจน์  แมกซิมา

บางแพลตฟอร์มก็วางนิพจน์ไว้ทางซ้ายและวางตัวแปรไว้ทางขวา

 MOVE นิพจน์ TO ตัวแปร  ภาษาโคบอล นิพจน์ → ตัวแปร  ภาษาทีไอ-เบสิก, ภาษาเบสิกคาสิโอ (เครื่องคิดเลข) นิพจน์ -> ตัวแปร  ภาษาอาร์

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

 (setq ตัวแปร นิพจน์)  ภาษาลิสป์, ภาษาสกีม (set!), ฯลฯ set ตัวแปร นิพจน์  ภาษาทีซีแอล

 การดำเนินการ 
การดำเนินการกำหนดค่าตามความหมายแล้วเป็นการเปลี่ยนแปลงสถานะปัจจุบันของโปรแกรมที่กำลังทำงานอยู่ ดังนั้นการกำหนดค่าจึงขึ้นอยู่กับแนวคิดของตัวแปร ในการกำหนดค่าหนึ่ง ๆ นิพจน์ จะถูกประเมินค่าในสถานะปัจจุบันของโปรแกรม และ ตัวแปร จะถูกกำหนดด้วยค่าที่ประเมินนั้น แทนที่ค่าที่มีอยู่ก่อนหน้าในตัวแปร ตัวอย่างเช่น สมมติให้ 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)D.W. Barron et al., "The main features of CPL", Computer Journal 6:2:140 (1963). full text (subscription)

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

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

ภาษาไพทอนถือว่าการกำหนดค่าไม่ใช่นิพจน์ ดังนั้นมันจึงไม่มีค่าใด ๆ ส่งคืนกลับมา

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

 การกำหนดค่าปกติกับการกำหนดค่าเชิงเดี่ยว 

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

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

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

หลายภาษาใช้สัญกรณ์ที่แตกต่างกันสำหรับการดำเนินการแต่ละชนิด ตัวอย่างเช่น ตัวดำเนินการกำหนดค่าใช้เครื่องหมายเท่ากับตัวเดียว = ในขณะที่ตัวดำเนินการเทียบเท่าใช้เครื่องหมายเท่ากับสองตัว == ในภาษาซี แต่ในบางภาษาเช่นภาษาเบสิก เครื่องหมายเท่ากับตัวเดียวใช้แทนการดำเนินการทั้งสอง ซึ่งความหมายของมันจะพิจารณาจากบริบท

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

 อ้างอิง 

 ดูเพิ่ม 
 การยึดเหนี่ยวกับชื่อ
 การรวมเป็นหนึ่ง

หมวดหมู่:มโนทัศน์ภาษาโปรแกรม