การประกาศตัวแปรที่ผันแปรหมายความว่าอย่างไร


9

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


1
หากคุณกำลังอ่านvolatileตัวแปรอายุและมันบอกว่า 5 และคุณอ่านมันอีกครั้งในปีหน้าคุณรับประกันว่าจะได้รับ 6
5gon12eder

@ 5gon12eder ฉันเข้าใจความผันผวนหมายความว่าบางสิ่งอาจมีการเปลี่ยนแปลงอย่างรวดเร็วและง่ายดาย แต่ทำงานอย่างไร : S
Vikaton

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

คำตอบ:


11

volatile หมายถึงโปรเซสเซอร์อื่นหรืออุปกรณ์ I / O หรือบางอย่างสามารถเปลี่ยนแปลงตัวแปรจากภายใต้คุณ

ด้วยตัวแปรธรรมดาขั้นตอนของโปรแกรมของคุณเป็นสิ่งเดียวที่จะเปลี่ยนแปลงได้ ตัวอย่างเช่นถ้าคุณอ่าน5จากตัวแปรและคุณไม่เปลี่ยนมันจะยังคงมี5อยู่ เนื่องจากคุณสามารถวางใจได้ว่าโปรแกรมของคุณไม่จำเป็นต้องใช้เวลาในการอ่านตัวแปรอีกครั้งในครั้งต่อไปที่คุณต้องการใช้ คอมไพเลอร์ C ++ นั้นฉลาดในการสร้างรหัสที่เพิ่งจำ5ได้

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

การเปรียบเทียบสำหรับเด็กอายุ 5 ปี
สมมติว่าคุณวางกระดาษแผ่นใหญ่ลงบนโต๊ะ ในมุมหนึ่งของกระดาษคุณเขียนคะแนนปัจจุบันของเกมต่อเนื่อง, 3 to 4. จากนั้นคุณไปที่ด้านตรงข้ามของโต๊ะและเริ่มเขียนเรื่องราวเกี่ยวกับเกม เพื่อนของคุณที่กำลังดูเกมจะอัพเดตคะแนนในมุมนั้นเมื่อเกมดำเนินต่อไป เธอจะลบและเขียน3 to 43 to 5

เมื่อคุณใส่คะแนนเกมลงในเรื่องราวของคุณคุณสามารถ:

  1. จดคะแนนสุดท้ายที่คุณอ่านโดย3 to 4สมมติว่ามันไม่ได้เปลี่ยนอย่างสนุกสนาน (หรือไม่รังเกียจถ้าทำ) หรือ
  2. เดินไปรอบ ๆ ด้านตรงข้ามของโต๊ะเพื่ออ่านคะแนนปัจจุบัน (ซึ่งเกิดขึ้น3 to 5ตอนนี้) และเดินกลับ นั่นเป็นวิธีที่volatileตัวแปรทำหน้าที่

11

volatile หมายถึงสองสิ่ง:

  1. ค่าของตัวแปรอาจเปลี่ยนแปลงได้โดยไม่ต้องมีรหัสของคุณเปลี่ยนแปลง ดังนั้นเมื่อใดก็ตามที่คอมไพเลอร์อ่านค่าของตัวแปรมันอาจไม่คิดว่ามันจะเหมือนกับครั้งสุดท้ายที่อ่านหรือว่าเป็นค่าเดียวกับค่าสุดท้ายที่เก็บไว้ แต่ต้องอ่านอีกครั้ง

  2. การกระทำของการเก็บค่าตัวแปรแปรปรวนเป็น "ผลข้างเคียง" ซึ่งสามารถสังเกตได้จากภายนอกดังนั้นคอมไพเลอร์ไม่ได้รับอนุญาตให้ลบการกระทำของการเก็บค่า; ตัวอย่างเช่นหากเก็บสองค่าไว้ในแถวคอมไพเลอร์จะต้องเก็บค่าไว้สองครั้ง

ตัวอย่างเช่น:

i = 2; 
i = i; 

คอมไพเลอร์ต้องเก็บหมายเลขสองอ่านตัวแปร i เก็บตัวแปรที่อ่านเป็น i

มีสถานการณ์อื่น: หากฟังก์ชั่นใช้setjmpและlongjmpถูกเรียกใช้ตัวแปรท้องถิ่นที่ระเหยได้ทั้งหมดของฟังก์ชั่นจะรับประกันว่าจะมีค่าสุดท้ายที่เก็บไว้ - นี่ไม่ใช่กรณีที่มีตัวแปรท้องถิ่นที่ไม่ลบเลือน


มีปัญหาเล็กน้อยที่นี่ ปัญหาหนึ่งที่ลึกซึ้งคือการที่คุณได้ลักษณะผันผวนอ่านเป็นลักษณะของการเป็นตัวแปรในเมื่อความจริงพวกเขามีลักษณะของวิธีการที่ตัวแปรที่มีการเข้าถึง ถ้าเรามีตัวแปรiและความคุ้มค่าpi = &iแล้วx = *piไม่อ่านจากiแต่อ่านที่ไม่ได้รับประกันว่าจะมีความหมายมีความผันผวน
Eric Lippert

1
@EricLippert: หากiมีการประกาศตามvolatile int iนั้นpiจะต้องมีการประกาศเป็นvolatile int *piซึ่งในกรณีนี้*piคือการเข้าถึงที่ระเหยได้ไม่?
Jon Purdy

2

คำอธิบายบทคัดย่อ
ทั้ง C และ C ++ มีแนวคิดของเครื่องนามธรรม เมื่อรหัสใช้ค่าของตัวแปรบางตัวเครื่องนามธรรมบอกว่าการนำไปปฏิบัตินั้นต้องเข้าถึงค่าของตัวแปรนั้น รหัสของฟอร์มstatement_A; statement_B; statement_C;จะต้องถูกดำเนินการตามลำดับที่ระบุ นิพจน์ทั่วไปของทั้งสามคำสั่งนั้นจะต้องคำนวณใหม่ทุกครั้งที่เกิดขึ้น

ต่อเครื่องที่เป็นนามธรรมให้ลำดับของงบstatement_A; statement_B; statement_C;การดำเนินงานจะต้องดำเนินการstatement_Aอย่างครบถ้วนแล้วและในที่สุดก็statement_B statement_Cการใช้งานไม่สามารถจำได้ว่าคุณกำหนดageค่าเป็น 5 ทุกคำสั่งที่อ้างอิงageต้องเข้าถึงค่าของตัวแปรนั้นแทน

จะไม่มีความจำเป็นสำหรับvolatileคำหลักหากการใช้งานดำเนินการอย่างเคร่งครัดรหัส C หรือ C ++ ต่อข้อกำหนดนามธรรมเครื่อง เครื่องนามธรรม C และ C ++ ไม่มีแนวคิดของการลงทะเบียนไม่มีแนวคิดของนิพจน์ย่อยทั่วไปและลำดับการดำเนินการนั้นเข้มงวด

ทั้งสองภาษายังมีเป็นถ้ากฎ การนำไปใช้นั้นเป็นไปตามมาตรฐานตราบใดที่การใช้งานนั้นดำเนินการราวกับว่าได้ดำเนินการตามข้อกำหนดของเครื่องนามธรรม คอมไพเลอร์สามารถสันนิษฐานว่าตัวแปรที่ไม่ลบเลือนไม่ได้เปลี่ยนค่าระหว่างการมอบหมาย ตราบใดที่มันไม่ได้ทำลายas-ifกฎลำดับstatement_A; statement_B; statement_C;อาจจะมีการดำเนินการโดยการดำเนินการเป็นส่วนหนึ่งของstatement_Cนั้นเป็นส่วนหนึ่งของstatement_Aแล้วทั้งหมดของstatement_Bแล้วส่วนที่เหลือของและสุดท้ายส่วนที่เหลือของstatement_Astatement_C

กฏas-ifเหล่านั้นใช้ไม่ได้กับvolatileตัวแปร ในแง่ของvolatileตัวแปรและฟังก์ชั่นการใช้งานจะต้องทำในสิ่งที่คุณบอกให้ทำและในลำดับที่คุณบอกให้ทำสิ่งต่าง ๆ

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

คำตอบของ ELI5

หมายความว่าอย่างไรเมื่อคอมไพเลอร์ไม่ "เพิ่มประสิทธิภาพ" ที่อยู่หน่วยความจำ

ที่อยู่หน่วยความจำ "เพิ่มประสิทธิภาพ" เป็นแนวคิดขั้นสูงสิ่งที่ไม่ได้อยู่ในขอบเขตของความสามารถของเด็กอายุห้าปี เป็นไปตามมาตรฐานอายุห้าขวบจะทำในสิ่งที่คุณบอกให้ทำไม่มากไม่น้อย ด้วยvolatileคุณกำลังบอกให้การใช้งานทำตัวเหมือนห้า: ไม่คิดไม่มีการปรับให้เหมาะสม แต่การใช้งานจะต้องทำในสิ่งที่รหัสบอกให้ทำ


1

(ไม่ใช่ -) สารระเหยเป็นคำแนะนำสำหรับคอมไพเลอร์วิธีการปรับโค้ดให้เหมาะสม (จากมุมมองการประกอบโค้ดโค้ดที่สร้างขึ้น):

  • non volatileหมายความว่าคอมไพเลอร์ปัจจุบันของคุณตัดสินใจว่าจะวางตำแหน่งของตัวแปรหรือวิธีที่ค่าตัวแปร s ถูกโอนย้ายไปยังรูทีนย่อย
    • ในที่อยู่หน่วยความจำคงที่
    • บนสแต็ก [สัมพันธ์กับตัวประมวลผลปัจจุบัน stackpointer],
    • บน heap [สัมพันธ์กับ basepointer ปัจจุบันของโปรเซสเซอร์]
    • ในการลงทะเบียนโปรเซสเซอร์
    • ...
  • volatileหมายความว่าคอมไพเลอร์ไม่สามารถปรับตัวแปรให้เหมาะสมเพราะอย่างอื่นนอก main-cpu-s controllers (เช่น io-processer แยกต่างหาก) สามารถเปลี่ยนค่านี้

0

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

ใช่เหตุผลหนึ่งก็เพราะคนอื่นอาจเปลี่ยนคุณค่านั้นให้กับเรา อีกเหตุผลคือเราอาจเปลี่ยนค่านั้นให้กับคนอื่น คนอื่นไม่ว่าจะเป็นคนที่เปลี่ยนแปลงมันสำหรับเราหรือคนที่เรากำลังเปลี่ยนมันอาจจะเป็นฮาร์ดแวร์ / ตรรกะหรือซอฟต์แวร์ มักใช้เพื่อกำหนดการเข้าถึงการควบคุมและการลงทะเบียนสถานะในโปรแกรมฝังตัวโลหะเปลือยเขียนหรืออ่านจากฮาร์ดแวร์ ซอฟแวร์พูดคุยกับซอฟต์แวร์อธิบายในคำตอบอื่น ๆ

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

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.