อะไรคือความแตกต่างระหว่างภาษาที่รวบรวมและแปลความหมาย?


118

หลังจากอ่านเนื้อหาบางส่วนเกี่ยวกับเรื่องนี้แล้วฉันยังไม่แน่ใจว่าความแตกต่างระหว่างภาษาคอมไพล์และภาษาที่ตีความหมายคืออะไร ฉันบอกว่านี่เป็นหนึ่งในความแตกต่างระหว่าง Java และ JavaScript มีใครช่วยฉันทำความเข้าใจได้ไหม

คำตอบ:


165

อะไรคือความแตกต่างระหว่างภาษาที่รวบรวมและแปลความหมาย?

ความแตกต่างไม่ได้อยู่ในภาษา มันมีอยู่ในการดำเนินการ

เมื่อนำสิ่งนั้นออกจากระบบของฉันนี่คือคำตอบ:

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

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

    • คำสั่งไบนารีสำหรับเครื่องเสมือนซึ่งมักเรียกว่าbytecodeเช่นเดียวกับที่ทำใน Lua, Python, Ruby, Smalltalk และระบบอื่น ๆ อีกมากมาย (วิธีนี้ได้รับความนิยมในปี 1970 โดยระบบ UCSD P และ UCSD Pascal)

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

    • การแสดงโทเค็นของโปรแกรมต้นทางคล้ายกับ Tcl

    • อักขระของโปรแกรมต้นทางเช่นเดียวกับที่ทำใน MINT และ TRAC

สิ่งหนึ่งที่ทำให้ปัญหาซับซ้อนคือสามารถแปล (คอมไพล์) bytecode เป็นคำแนะนำของเครื่องดั้งเดิมได้ ดังนั้นการใช้งานแบบ intepreted ที่ประสบความสำเร็จในที่สุดอาจได้รับคอมไพเลอร์ หากคอมไพลเลอร์ทำงานแบบไดนามิกเบื้องหลังมักเรียกว่าคอมไพเลอร์แบบทันเวลาหรือคอมไพเลอร์ JIT JIT ได้รับการพัฒนาสำหรับ Java, JavaScript, Lua และฉันกล้าพูดภาษาอื่น ๆ อีกมากมาย เมื่อถึงจุดนั้นคุณสามารถใช้งานแบบไฮบริดซึ่งมีการตีความโค้ดบางส่วนและมีการคอมไพล์โค้ด


7
ครับผมมีคำถามต่อไปนี้ 1. คำว่า "อย่างอื่น" เขียนในภาษาใด 2. และในบริบทของ JavaScript "อย่างอื่น" นั้นแตกต่างกันไปในแต่ละเบราว์เซอร์หรือไม่? 3. สมมติว่าสคริปต์ของฉันทำงานใน Google Chrome และ Internet Explorer มันถูกตีความเหมือนกันในทั้งสองเบราว์เซอร์หรือไม่
JavaHopper

@ Norman นั่นเป็นคำอธิบายที่ยอดเยี่ยม อย่างไรก็ตามนี่คือความสับสนที่ฉันยังคงมีอยู่ ในการนำไปใช้งานที่คอมไพล์แล้วโปรแกรมดั้งเดิมจะถูกแปลงเป็นคำสั่งของเครื่อง มาได้ยังไง? ตัวอย่างเช่นฉันคิดว่า C หลังจากการคอมไพล์แล้วจะสร้างรหัสแอสเซมบลีซึ่งจะต้องประกอบอีกครั้งโดยแอสเซมเบลอร์เนทีฟในรหัสเครื่องของเครื่อง แล้วมันแตกต่างจาก VM (python หรือ JVM เป็นต้น) อย่างไรในกรณีของภาษาที่ตีความ?
qre0ct

58

Java และ JavaScript เป็นตัวอย่างที่ไม่ดีเป็นธรรมที่จะแสดงให้เห็นถึงความแตกต่างนี้เพราะทั้งสองจะถูกตีความภาษา Java (ตีความ)และ C (หรือ C ++) (คอมไพล์)อาจเป็นตัวอย่างที่ดีกว่า

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

โดยทั่วไปโค้ดที่คอมไพล์สามารถดำเนินการได้โดยตรงโดย CPU ของคอมพิวเตอร์ นั่นคือรหัสปฏิบัติการถูกระบุไว้ในภาษา "เนทีฟ" ของ CPU ( ภาษาแอสเซมบลี )

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

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


8
Java ถูกตีความ? จากวิกิพีเดีย: "โดยทั่วไปแอปพลิเคชัน Java จะถูกคอมไพล์เป็น bytecode (ไฟล์คลาส) ที่สามารถทำงานบน Java Virtual Machine (JVM) ได้โดยไม่คำนึงถึงสถาปัตยกรรมคอมพิวเตอร์"
Personman

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

5
ฉันคิดว่าคุณหมายความว่าไฟล์คลาสนั้นถูกตีความโดย Java VM นั่นเป็นเรื่องที่สมเหตุสมผล แต่แหล่งที่มาของ java นั้นถูกคอมไพล์ไปยัง Java VM bytecode คุณสามารถสร้าง Java Machine ทางกายภาพที่ไม่ต้องการให้ VM ตีความเป็นรหัสเครื่องของสถาปัตยกรรมอื่น ดังนั้นจึงดูเหมือนถูกต้องกว่าที่จะบอกว่าคอมไพล์ Java ถึงกระนั้นนี่ก็เป็นตัวอย่างที่ดีของวิธีการที่ความแตกต่างสับสนและเป็นไปตามอำเภอใจ ท้ายที่สุดแล้ว C ที่คอมไพล์แล้วถูกตีความโดย CPU ใช่ไหม?
Personman

13
Java เป็นตัวอย่างที่ค่อนข้างแย่ของภาษาที่คอมไพล์หรือตีความเพราะโดยพื้นฐานแล้วมันเป็นทั้งสองอย่าง ถ้าจะเปรียบเทียบฉันจะใช้ C กับ Lisp เพื่อไม่ให้เกิดความสับสน
Bill the Lizard

7
@stakx - โดยปกติแล้ว Java bytecodes จะถูกคอมไพล์เป็นโค้ดเนทีฟโดยคอมไพเลอร์ JIT วิธีเดียวที่จะได้รับพฤติกรรมของล่ามที่บริสุทธิ์คือการปิดคอมไพเลอร์ JIT อย่างชัดเจนเมื่อเปิดใช้งาน JVM
Stephen C

15

นี่คือความแตกต่างพื้นฐานระหว่างภาษาคอมไพเลอร์กับภาษาล่าม

ภาษาคอมไพเลอร์

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

ภาษาของล่าม:

  • ใช้คำสั่งเดียวเป็นอินพุตเดียวและดำเนินการตามคำสั่ง
  • ไม่มีการสร้างรหัสวัตถุระดับกลาง
  • เช่น Perl, Python, Matlab
  • โปรแกรมที่ตีความทำงานช้าลงเนื่องจากการคอมไพล์และการดำเนินการเกิดขึ้นพร้อมกัน
  • ความต้องการหน่วยความจำน้อยกว่า
  • ข้อผิดพลาดจะแสดงขึ้นสำหรับทุกคำสั่ง
  • ซอร์สโค้ด - ล่าม - เอาต์พุต

5

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

หากคุณต้องการข้อมูลเพิ่มเติมเพียงแค่ Google สำหรับ "ความแตกต่างระหว่างคอมไพเลอร์และล่าม"


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

โปรดทราบว่าภาษาเช่น Java, C # และ JavaScript ซึ่งเกือบจะท่วมทั่วโลกในการเขียนโปรแกรมในปัจจุบันจะไม่เป็นธรรมที่จะกล่าวว่า "รหัสที่คอมไพล์นั้นดีกว่าสำหรับการใช้งานที่จริงจัง"
Sisir

2

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

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

ในการคอมไพล์ซอร์สโค้ดคือการรันโปรแกรมที่สร้างไบนารีไฟล์ที่เรียกใช้งานได้ซึ่งเมื่อรันมีลักษณะการทำงานที่กำหนดโดยซอร์ส ตัวอย่างเช่น javac รวบรวมไฟล์ human-readbale .java ลงในไฟล์. class ที่เครื่องอ่านได้

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


ในขณะที่ Java แปลเป็น bytecode เป็นครั้งแรกและในขณะที่เรียกใช้ JVM เท่านั้นที่จะแปลงเป็นรหัสเครื่อง ถูกต้องหรือไม่ที่จะบอกว่าเรียบเรียงและไม่ตีความ
Sisir

1
ฉันเดาว่าคุณสามารถพูดได้ว่า Java bytecode ถูกตีความแน่นอน แต่ไม่มีใครเขียน Java bytecode โดยปกติ Java จะถูกคอมไพล์เป็น bytecode
Personman

2

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


0

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

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

ขั้นแรกเราต้องกำหนดโดยไม่มีล่ามและคอมไพเลอร์ที่คลุมเครือ:

ล่ามภาษาXเป็นโปรแกรม (หรือเครื่องหรือเพียงแค่ชนิดของกลไกโดยทั่วไปบางคน) ที่รันโปรแกรมใด ๆPเขียนในภาษาXดังกล่าวว่าจะดำเนินการผลกระทบและประเมินผลตามข้อกำหนดของX

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

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

ตอนนี้เราสามารถจำแนกภาษาการเขียนโปรแกรมเบื้องต้นได้เป็น 3 ประเภทโดยขึ้นอยู่กับการใช้งานทั่วไป:

  • ภาษาคอมไพล์ยาก: เมื่อโปรแกรมถูกคอมไพล์ทั้งหมดเป็นภาษาเครื่อง ตัวแปลเดียวที่ใช้คือ CPU ตัวอย่าง: โดยปกติในการรันโปรแกรมในภาษา C ซอร์สโค้ดจะถูกคอมไพล์เป็นภาษาเครื่องซึ่งจะเรียกใช้งานโดย CPU
  • ภาษาที่ตีความ: เมื่อไม่มีการรวบรวมส่วนใดส่วนหนึ่งของโปรแกรมต้นฉบับเป็นภาษาเครื่อง กล่าวอีกนัยหนึ่งคือไม่มีการสร้างรหัสเครื่องใหม่ ดำเนินการเฉพาะรหัสเครื่องที่มีอยู่เท่านั้น ล่ามอื่น ๆ กว่า CPU ยังต้องใช้ (โดยปกติโปรแกรม) .example: ในการดำเนินงานที่เป็นที่ยอมรับของงูใหญ่ซอร์สโค้ดจะรวบรวมคนแรกที่จะPython bytecodeแล้วว่า bytecode จะถูกดำเนินการโดย CPython โปรแกรมล่ามPython bytecode
  • ภาษาคอมไพล์แบบซอฟต์: เมื่อใช้ล่ามอื่นที่ไม่ใช่ซีพียู แต่บางส่วนของโปรแกรมต้นฉบับอาจถูกคอมไพล์เป็นภาษาเครื่อง นี่เป็นกรณีของ Java ที่ซอร์สโค้ดถูกคอมไพล์เป็น bytecode ก่อนจากนั้น bytecode อาจถูกตีความโดย Java Interpreter และ / หรือคอมไพล์เพิ่มเติมโดยคอมไพเลอร์ JIT

บางครั้งภาษาที่คอมไพล์แบบอ่อนและยากจะอ้างอิงถึงการคอมไพล์อย่างง่าย ๆ ดังนั้นจึงมีการกล่าวถึง C #, Java, C, C ++

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

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