ทำไม C ++ ถึงเขียนคอมไพเลอร์?


14

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


3
"คอมไพเลอร์จำนวนมากเขียน [... ] ใน C ++" - มีการอ้างอิงอะไรบ้าง? อันไหน? อะไรที่ทำให้คุณคิดว่า C ++ มักใช้ในการสร้างคอมไพเลอร์มากกว่าภาษายอดนิยมอื่น ๆ
Doc Brown

6
@DocBrown Well, Clang และ MSVC ส่วนใหญ่เขียนใน C ++, gcc มีบิตของ C ++ ในตอนนี้, Java JVM ถูกเขียนใน C ++ stackoverflow.com/questions/410320/what-is-java-written-inและsuperuser com / คำถาม / 136136 / …
Klaim

@DocBrown DMD คอมไพเลอร์อ้างอิงสำหรับ D เขียนด้วยภาษา C ++
ratchet freak

3
ใครบอกว่าเป็นตัวเลือกที่ดี?
Phil

1
@ ฟิลคุณคิดว่าพวกเขาเลือกตัวเลือกนี้โดยไม่คำนึงถึงทางเลือกหรือไม่? มันไม่ใช่ตัวเลือก "ดี" แต่เป็นตัวเลือก "ประสิทธิภาพ"
Klaim

คำตอบ:


24

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


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

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

3
@Giorgio และ Oleksi: ฉันยืนยันได้ทั้งคู่ ฉันเขียนคอมไพเลอร์กับ Haskell สำหรับภาษาโลกแห่งความจริง มันเป็นแบบที่ดีจริงๆ แต่บางครั้งฉันพลาด OO ไป ถ้าฉันต้องเขียนคอมไพเลอร์อื่นฉันจะต้องเลือก Haskell แต่นี่เป็นกรณีพิเศษจริงๆ ฉันจะไม่เลือก Haskell โดยไม่ลังเลกับโครงการประเภทอื่น
scarfridge

27
ทำไมคุณต้องมีภาษาที่มี "ด้านต่ำ" เพื่อสร้างรหัส? ฉันไม่เห็นว่าทั้งสองเชื่อมต่อกันอย่างไร
phant0m

5
คุณไม่จำเป็นต้องใช้ "ระดับต่ำ" ในการสร้างโค้ดมากกว่าที่คุณต้องการตัวระบุ Unicode เพื่อให้สามารถเขียนข้อความภาษาญี่ปุ่นลงในไฟล์ได้
dan04

17

ประสบการณ์ของฉันไม่เห็นด้วยกับหลักฐานของคุณที่นี่ ในความเป็นจริงสำหรับภาษาที่ใช้งานทั่วไปในระดับสูงเป็นวิธีปฏิบัติทั่วไปในการเขียนคอมไพเลอร์ในภาษาเดียวกับภาษาต้นฉบับ (ภาษาที่กำลังรวบรวม) ตัวอย่างเช่น:

  • คอมไพเลอร์ Java ของ Sun เขียนเป็น Java
  • คอมไพเลอร์ Scala เขียนใน Scala
  • คอมไพเลอร์ C # ของ Mono เขียนด้วยภาษา C #
  • คอมไพเลอร์ Smalltalk ของ Squick เขียนใน Smalltalk
  • ... และอื่น ๆ อีกมากมาย

ข้อยกเว้นคือคอมไพเลอร์ front-end ที่ถูกเขียนสำหรับเฟรมเวิร์กคอมไพเลอร์ที่มีอยู่เช่น GCC, LLVM หรือ Polyglot ซึ่งจะถูกเขียนในภาษาของเฟรมเวิร์กหรือคอมไพเลอร์ที่พึ่งพาตัวแยกวิเคราะห์ที่มีอยู่เช่น Yacc เนื่องจาก GCC, LLVM และ Yacc เป็นเรื่องธรรมดาเครื่องมือที่สร้างขึ้นใน C และ C ++ จึงเป็นแรงจูงใจให้นักเขียนคอมไพเลอร์ใช้พวกเขาซึ่งอาจนำไปสู่ ​​C และ C ++ ได้รับส่วนแบ่งมากในการกระจายการใช้ภาษาคอมไพเลอร์


2
ฉันคิดว่ามันเกี่ยวข้องกับคนเขียนคอมไพเลอร์รู้ดีและชอบภาษาที่พวกเขาเขียนคอมไพเลอร์มากกว่าสำหรับเหตุผลทางเทคนิควัตถุประสงค์
โทมัส Bonini

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

1
คอมไพเลอร์ Java ของ Sun เขียนด้วยภาษา C ++: stackoverflow.com/questions/410320/what-is-java-written-in
Klaim

12
@ คำติชมทำให้คุณสับสนสองผลิตภัณฑ์ที่นี่ หนึ่งคือคอมไพเลอร์ Java ของ Sun ( javaccommand-line) ซึ่งรวบรวม Java เป็น Java Bytecode มันเขียนใน Java - ฉันได้แก้ไขมาหลายครั้งตัวเองและคุณสามารถเรียกดูแหล่งที่มา Java ออนไลน์ อีกอันคือคอมไพเลอร์ทันเวลาที่ฝังอยู่ใน Hotspot JVM ซึ่งรวบรวม Java Bytecodeกับรหัสเครื่องดั้งเดิม เช่นเดียวกับ JVM ส่วนใหญ่ที่เขียนด้วยภาษา C ++ แต่ไม่ใช่คอมไพเลอร์ Javaเพราะจริงๆแล้วมันไม่รู้อะไรเกี่ยวกับภาษาจาวา
โอ๊ก

@ โอ๊ยถูกต้องแน่นอน! กล่าวอีกนัยหนึ่ง JVM! = javac
Paul Draper

6

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

  • CoffeeScriptคอมไพล์ไปยัง JavaScript คอมไพเลอร์ที่ถูกเขียนใน CoffeeScript
  • Script #คอมไพล์ C # ลงใน JavaScript คอมไพเลอร์ที่ถูกเขียนถ้าฉันจำได้ดี C #
  • เป็นต้น

ภาษาที่คุณเลือกเพื่อเขียนคอมไพเลอร์ขึ้นอยู่กับบริบท ตัวอย่างเช่นการทำงานในโครงการที่รวบรวมภาษาที่ได้จาก PHP ไปเป็นโค้ด PHP พื้นเมืองฉันใช้ PHP และ C # ผสมกันในการเขียนคอมไพเลอร์เพราะมันทำให้ฉันเข้าใจทักษะของฉันมากที่สุด บุคคลอื่นจะเลือก Python หรือ Java และ PHP หรือ C ++ ด้วย JavaScript หรืออะไรก็ตาม

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

โปรดทราบว่าเพื่อให้มีความคล่องแคล่วมากขึ้นคุณอาจเลือกภาษาต้นฉบับเพื่อเขียนคอมไพเลอร์เอง มันเป็นสิ่งที่เกิดขึ้นกับคอมไพเลอร์ CoffeeScript และคอมไพเลอร์อื่น ๆ มันยังเป็นที่นิยมของ IDEs: หนึ่งใน Visual Studio แรกนั้นถูกสร้างโดยใช้ Visual Studio เดียวกัน


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

5
เหตุผลก็คือทำให้คอมไพเลอร์ตัวเองเป็นโปรแกรมทดสอบได้ทันที มันน่าจะเป็นโปรแกรมที่ใหญ่ที่สุดสำหรับคอมไพเลอร์นั้นสักพัก

6

ฉันมักจะตั้งคำถามขั้นพื้นฐานที่นี่ ในขณะที่ C และ C ++ ทำงานได้ดีอย่างสมบูรณ์แบบสำหรับการเขียนคอมไพเลอร์ แต่ภาษาอื่น ๆ อีกสองสามภาษาดูเหมือนจะทำงานได้ดีอย่างสมบูรณ์สำหรับงานนี้เช่นกัน

ขึ้นอยู่กับภาษาที่คุณกำลังรวบรวม สำหรับภาษาขนาดเล็กที่เรียบง่าย C และ Pascal ทำงานได้ค่อนข้างดี หากคุณกำลังจะรวบรวมสิ่งที่มีขนาดใหญ่และซับซ้อนคอมไพเลอร์ของคุณก็จะใหญ่และซับซ้อนเช่นกันซึ่งในกรณีนี้คุณสมบัติพิเศษของ C ++ สำหรับการจัดระเบียบและการทำงานกับโปรแกรมขนาดใหญ่นั้นมีประโยชน์ ที่ไม่เฉพาะเจาะจงมากในการรวบรวม แต่เพียงคุณสมบัติที่มีประโยชน์สำหรับโปรแกรมขนาดใหญ่โดยทั่วไป

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


2
AST = ต้นไม้ไวยากรณ์บทคัดย่อ RE = นิพจน์ปกติ
chaotic3quilibrium

5

คอมไพเลอร์อาจใช้งานในภาษาที่ทันสมัยใด ๆ อย่างไรก็ตามหนึ่งในข้อกำหนดที่สำคัญที่สุดจากคอมไพเลอร์คือต้องรวดเร็ว

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


11
ข้อกำหนดที่สำคัญอีกประการหนึ่งคือรหัสที่สร้างขึ้นถูกต้อง - ฉันต้องการคอมไพเลอร์ที่ช้าฉันสามารถเชื่อถือได้มากกว่าโค้ดที่รวดเร็วซึ่งสร้างรหัสที่ไม่ถูกต้อง

2
แม้ว่ามันจะเป็นไปได้ที่จะเพิ่มประสิทธิภาพ C ++ อย่างหนัก แต่ก็มี ... ค่อนข้างมาก ... น้อยกว่ารหัส C ++ ที่ดีที่สุด
Donal Fellows

2
@ DonalFellows หมุนวิธีอื่น: สามารถเขียนโค้ดที่ดีที่สุดในภาษาใดก็ได้ แต่มีการเพิ่มประสิทธิภาพที่ไม่สามารถเปิดใช้งานในภาษาอื่นที่ไม่ใช่ C ++ (นอกเหนือจาก Assembler ฉันไม่รวม C เพราะขาด ของโครงสร้างระดับสูงช่วยให้การอินไลน์ที่แข็งแกร่งขึ้น)
Klaim

@ user1249 - ไม่มีเหตุผลที่ความเร็วของรหัส C ++ จะทำให้มันเป็นรถถังใด ๆ ฉันต้องการคอมไพเลอร์ที่เร็วและถูกต้องมากกว่าคอมไพเลอร์ที่ช้าและถูกต้อง
gnasher729

3

ฉันสงสัยว่าตัวกระตุ้นสำคัญสำหรับการใช้งานของพวกเขาคือเอาต์พุตของ Lex / Yacc / Bison เป็น (ส่วนใหญ่) ใน C เนื่องจากนั่นเป็นมาตรฐานมาเป็นเวลานานจึงมีโมเมนตัม

ไม่ใช่ว่าเป็นเหตุผลที่ดีโดยเฉพาะ ...


จริงๆแล้วมันไม่ได้ทำให้ฉันพึงพอใจ แต่ขอขอบคุณที่ลอง
Kobra

ที่ไม่ตอบคำถาม "ทำไมต้องเลือก C ++ มากกว่า C สำหรับการสร้างคอมไพเลอร์"
Doc Brown

3
ไม่ใช่เหตุผลที่ดีเลย มีเครื่องมือคล้ายกับ Lex และ Yacc สำหรับแพลตฟอร์มหลายแห่ง PLY และ ANTLR เป็นต้น
user16764

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

@delnan: ใช่ แต่พวกเขาอาจเริ่มใช้สิ่งที่สร้างขึ้นเพื่อกำจัดสิ่งต่าง ๆ การสร้าง parser ด้วยมือเป็นขั้นตอนการเพิ่มประสิทธิภาพที่คุณไม่ต้องการทำจนกว่าคุณจะพิสูจน์ได้ว่าสิ่งอื่น ๆ ใช้งานได้
Martin York

1

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

ใน C ++ คุณสามารถมีกลไกเดียวกัน แต่จริงๆแล้วมันมีเวลาในการพัฒนาที่มีประสิทธิภาพเพราะการจัดการหน่วยความจำทั้งหมดของคุณสามารถถูกห่อหุ้มอยู่ภายใน Constructor และ Destructors ที่คุณไม่ต้องเรียกอย่างชัดเจน คอมไพเลอร์กำลังจัดสรรและเพิ่มทรัพยากรให้คุณ ขนาดของวัตถุแบบไดนามิกของคุณสามารถถูกห่อหุ้มได้เช่นกันถ้าคุณสร้างคลาสของคุณเองและดัชนีสามารถตรวจสอบการเข้าถึงขอบเขตโดยการใช้ตัวดำเนินการมากเกินไป [] abstractions เหล่านี้ช่วยทำให้โค้ดของคุณสะอาดขึ้นง่ายขึ้นเข้าใจและตรวจแก้จุดบกพร่องและทำให้การพัฒนาเร็วขึ้นแน่นอน

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


0

CompCertโครงการเป็นคอมไพเลอร์ C การวิจัยที่ไม่ได้เขียนใน C หรือ C ++ แต่ใน Ocaml และ Coq

สังเกตว่า C ++ เคยถูกแปลเป็น C (ในCfront ) ตอนนี้คุณสามารถใช้GCC Front-end เพื่อGimpleจากนั้นถ่ายโอน Gimple ไปยังฐานข้อมูลบางส่วนแล้วเขียน Gimple ไปยังนักแปลแอสเซมเบลอร์ของคุณ แต่เหตุผลทางกฎหมาย ( ข้อยกเว้นไลบรารีรันไทม์ของ GCC ) จำเป็นต้องมีคอมไพเลอร์เป็นโอเพนซอร์ส สอบถามรายละเอียดกับทนายความของคุณฉันไม่ใช่ทนายความ รุ่นเก่าของ GCC ได้รับการเขียนใน C (+ ภาษาเฉพาะโดเมนหลายภาษา) พร้อมกับส่วนหน้าสำหรับ C ++ บางตัว OpenWatcomอาจเป็นคอมไพเลอร์ C ++ ที่เขียนใน C (ฉันปล่อยให้คุณตรวจสอบ)

แหล่งที่มาของ Compcert นั้นฟรีสำหรับวัตถุประสงค์ทางวิชาการและการวิจัย หากคุณต้องการใช้มันอุตสาหกรรม (และถูกกฎหมาย) คุณต้องได้รับใบอนุญาตจาก Absint

ดูเพิ่มเติมนี้และว่าคำตอบสองคำถามที่เกี่ยวข้อง

ถ้าฉันถูกมอบหมายให้ 2020 เขียนคอมไพเลอร์ C (หรือ C ++) ตั้งแต่เริ่มต้น (ทำงานบน Linux บางทีคอมไพเลอร์ข้าม ) ฉันอาจจะไม่เขียนใน C ++ ฉันจะพิจารณาการเขียนโดยใช้Ocaml , Goหรือสนิม และฉันสามารถใช้มันกับFrama-C ได้หากได้รับอนุญาต หากจำเป็นต้องใช้รหัสใน C หรือ C ++ ฉันจะรหัสห้องสมุดเก็บขยะสำหรับมันอาจจะมีชั้นคงอยู่ -มีประโยชน์มากสำหรับการเพิ่มประสิทธิภาพโปรแกรมทั้งหมด - แล้วฉันจะพิจารณาวิธีmetaprogramming (สร้างรหัส C หรือ C ++ ส่วนใหญ่ของ คอมไพเลอร์ด้วยเครื่องมือ ad-hoc ของฉันบางทีBismonหรือRefPerSys ถ้าได้รับอนุญาต)

คุณสามารถค้นหาคอมไพเลอร์ C บางตัว (มากกว่าหรือน้อยกว่าโอเพนซอร์ส) ที่เขียนใน Common LISP หรือ Python (เช่นShivyCหรือnqcc ) ดูที่ZetaCด้วย

โปรดสังเกตว่าGCCรุ่นล่าสุดนั้นไม่มีการเข้ารหัสทางเทคนิคในภาษา C ++ ล้วน แต่เป็นภาษาเฉพาะของโดเมนที่เกี่ยวข้องกับ GCC หลายสิบภาษา (หลายแห่งเป็นภาษาทัวริงสมบูรณ์ ) ดูโครงการGCC MELTเก่าของฉัน

ฉันจะไม่แปลกใจถ้าใน GCC รุ่นอนาคตตัวแปลภาษา PythonหรือGuileบางตัวจะถูกฝังอยู่ภายใน (ตัวอย่างเช่นแทนที่ของ Pass manager ของ GCC)

ดูโครงการMILEPOST GCCด้วย

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