อะไรทำให้ C หยุดการคอมไพล์ / ตีความ / JIT'ed?


9

Java นั้นได้รับการยกย่องในเรื่องของการพกพาที่น่าทึ่งซึ่งฉันเข้าใจว่าเป็นเพราะ JVM คำถามของฉันคือสิ่งที่ห้ามไม่ให้ C ถูกคอมไพล์ / ตีความ / JIT'ed .. ถ้าเป็นเช่นนั้น C สามารถเขียนได้หนึ่งครั้งและทำให้มันทำงานบนอุปกรณ์ที่คุณเคยมี แต่นี่ไม่ใช่กลไกที่เป็นที่นิยมสำหรับการประมวลผลโปรแกรม C

อะไรคือข้อเสียของการประมวลผล C ด้วยวิธีนี้และอะไรคือข้อดีของการประมวลผล Java ด้วยวิธีนี้และไม่ได้รวบรวมรหัสเครื่องนอกเหนือจากความสามารถในการพกพาของหลักสูตร?


คำถามของคุณมีคำตอบที่ดีอยู่แล้วที่นี่: stackoverflow.com/questions/3925947/…
Doc Brown เมื่อ

2
@delnan จุดของฉันคือ "สิ่งที่หยุด C จากการรวบรวม / ตีความ / JIT'ed" จริงๆสูญเสียความหมายเมื่อภาษาอาจกำหนดเป้าหมายเครื่องเสมือนที่มี JIT หรือสถานการณ์ที่ vm จะระบุคุณสมบัติที่ขาดหายไปในฮาร์ดแวร์และ recompile รหัสเพื่อจับคู่ฮาร์ดแวร์ที่มีอยู่ (เช่นกับ OpenGL (เขียนเป็น C) บน OSX สำหรับการ์ดกราฟิกที่แตกต่างกัน) ไม่คุณไม่สามารถรวบรวมสิ่งที่จะกำหนดเป้าหมายเป็น lvm บนเครื่องหนึ่งและเรียกใช้เช่นนั้นในโปรเซสเซอร์อื่น แต่บรรทัดที่คอมไพล์ / ตีความ / JIT สามารถเบลอได้

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

2
ฉันงุนงงเกี่ยวกับบิตนี้: "สิ่งที่จะหยุด C จากการรวบรวม / [... ]" เอ่อไม่มีอะไรเลย
Andres F.

1
คอมไพเลอร์ C ค่อนข้างเร็วในวันนี้ดังนั้น "make myprog.c; myprog" อาจทำงานได้เร็วกว่าล่ามส่วนใหญ่
James Anderson

คำตอบ:


18

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

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

อะไรจะหยุด C จากการถูกตีความหรือ Jitted? ไม่มีอะไร แต่นั่นไม่ใช่ raison d'êtreของ C


6

ก่อนอื่นมันน่าสังเกตว่า JVM ของ Sun ถูกเขียนใน C. C เป็นภาษาที่ได้รับความนิยมอย่างมากเมื่อต้องการการพกพา

ภาษา C เป็นแบบพกพาแม้ว่าโปรแกรม C จำนวนมากจะไม่ นี่เป็นเพราะ C ไม่ได้มีข้อ จำกัด มากนักในโปรแกรมเมอร์หรือตั้งสมมติฐานมาก หากโปรแกรมเมอร์ C ต้องการให้โปรแกรมของเขาพกพาได้เขาจะต้องวางข้อ จำกัด เหล่านั้นไว้กับตัวเอง

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

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

reverse, การคอมไพล์ Java กับ native code ก็ทำได้เช่นเดียวกัน นั่นเป็นสิ่งที่ JIT ทำ ทำไมคุณถึงต้องการ ฉันแน่ใจว่ามีโครงการสัตว์เลี้ยงที่จะทำ "เพียงเพราะ" แต่พวกเขาไม่ได้ใช้อย่างจริงจัง


5

คุณพูดว่า:

Java นั้นได้รับการยกย่องในเรื่องของการพกพาที่น่าทึ่งซึ่งฉันเข้าใจว่าเป็นเพราะ JVM

และภายในประโยคแรกคุณคิดผิด Java ไม่สามารถพกพาได้เนื่องจาก JVM Java เป็นแบบพกพาเนื่องจากภาษา Java ถูกกำหนดในลักษณะที่ไม่ปล่อยให้ผู้พัฒนาใช้งานในลักษณะที่โปรแกรมอาจทำงานได้

ตัวอย่างเช่น Java มีสองประเภท "int" (จำนวนเต็ม 32 บิตที่เซ็นชื่อ) และ "ยาว" (จำนวนเต็ม 64 บิตที่เซ็นชื่อ) C และ C ++ มี "int" (ลงชื่ออย่างน้อย 16 บิต), "ยาว" (ลงชื่ออย่างน้อย 32 บิต) และ "ยาว" (ลงชื่ออย่างน้อย 64 บิต) นั่นเป็นเพราะ C ควรจะทำงานกับโปรเซสเซอร์ที่แตกต่างกันและทำให้พวกเขาทำงานแตกต่างกัน

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


เป็นไปได้ที่จะจำลองเลขคณิต 32 บิตบนเครื่อง 36- บิตและผลลัพธ์ของการดำเนินการทุกอย่างด้วย 0xFFFFFFFF เพื่อตัดให้เหลือ 32- บิต ดังนั้นเครื่องเหล่านี้สามารถใช้งาน Java ได้ แต่จะช้ากว่าถ้า Java อนุญาตให้ใช้ประเภทที่ไม่ใช่พื้นฐาน
dan04

4

Java เป็นแบบพกพาอย่างเฉพาะเพราะภาษาเป้าหมายโปรแกรม Java Virtual Machine ซึ่งเป็นชื่อที่แสดงถึงจะไม่ได้เป็นเครื่องจริง เนื่องจากคุณสามารถใช้เครื่องเสมือนกับสถาปัตยกรรมของเครื่องจริงหลายประเภทโปรแกรมที่ใช้ JVM จึงพกพาได้อย่างสูง

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


7
C เป็นแบบพกพาสูง คุณต้องคอมไพล์อีกครั้งบนแพลตฟอร์มเป้าหมายและหลีกเลี่ยงบิตเหล่านั้นที่ไม่ได้พกพาโดยเฉพาะและจงใจ
Robert Harvey

5
@RobertHarvey: ... เช่นสิ่งที่เป็นพื้นฐานเป็นขนาดของดั้งเดิมต่าง ๆ ? ;)
Mason Wheeler

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

3
@ RobertHarvey: ฉันจะบอกว่า C ทำให้มันเป็นไปได้ที่จะเขียนโปรแกรมพกพา แต่มันไม่ได้ทำให้มันง่ายโดยเนื้อแท้
Doc Brown

2
@RobertHarvey: คุณต้องการเริ่มสงครามศาสนาหรือไม่? ;-) ภาษาพกพาที่ฉันชอบคือ Python
Doc Brown

3

จริง ๆ แล้วมีการแปลเวอร์ชันของ Cแต่ส่วนใหญ่จะใช้สำหรับการทดลองที่รวดเร็วมากกว่าระบบการผลิต

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


3

ในทางทฤษฎีทั้ง C และ Java สามารถรวบรวมได้ทั้งรหัสเนทีฟตีความหรือเรียบเรียงไปยังเครื่องเสมือน

เหตุผลทางเทคนิคที่ C ไม่ได้ถูกคอมไพล์ไปยังเครื่องเสมือนคือไม่มีเครื่อง C มาตรฐานเสมือน

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


1

ที่จริงแล้วสิ่งนี้เสร็จสิ้น มีคอมไพเลอร์หลักที่รองรับการคอมไพล์ไปยัง LLVM (ฉันรู้ว่าเสียงดังกราวทำและฉันเชื่อว่า gcc ก็ทำได้เช่นกัน) LLVM นั้นสามารถเป็น JIT ได้เช่นเดียวกับโค้ด Java ที่คอมไพล์ลงไปเป็น bytecode ซึ่งเป็น JIT

อย่างไรก็ตามสิ่งที่ทำให้ java "cross platform" เมื่อเทียบกับ C คือ Java มีไลบรารีรันไทม์ขนาดใหญ่ซึ่งถูกย้ายไปยังหลายแพลตฟอร์ม C อย่างชัดเจนไม่เป็นไปตามกระบวนทัศน์นี้


C กับ POSIX สามารถพกพาได้ค่อนข้างดี (สำหรับ POSIX ทุกระบบ) หากคุณใช้รหัสด้วยความระมัดระวัง
Basile Starynkevitch

0

มีความแตกต่างที่สำคัญระหว่าง Java และ C. Java ถูกแยกออกจากระบบปฏิบัติการผ่าน Java virtual machine (JVM) JVM จะแยกระบบปฏิบัติการออกจากโปรแกรม แอ็พพลิเคชัน java อาจถาม JVM สำหรับหน่วยความจำอันหนึ่งและ JVM จะถาม OS สำหรับหน่วยความจำนั้น มี JVM จำนวนมากสำหรับแพลตฟอร์ม / ระบบปฏิบัติการที่แตกต่างกัน JVM เป็นสิ่งที่ทำให้โปรแกรมจาวาเดียวกันสามารถทำงานบนแพลตฟอร์มที่แตกต่างกัน

ด้วย C ไม่มีการแยก OS โปรแกรม C (โดยปกติ) จะทำงานโดยตรงที่ด้านบนของ OS ทำให้การโทรโดยตรงของระบบปฏิบัติการ สิ่งนี้ทำให้ความสัมพันธ์ของโปรแกรม C กับระบบปฏิบัติการ / แพลตฟอร์มเฉพาะ โปรแกรมที่ไม่น่าสนใจใด ๆ จะโทรเข้าสู่ระบบปฏิบัติการ นอกจากนี้โปรแกรม C จะถูกรวบรวมลงในรหัสเครื่องซึ่งเป็นฮาร์ดแวร์เฉพาะ โปรแกรม C ที่คอมไพล์แล้วสำหรับ x86 ไม่สามารถรันบนโปรเซสเซอร์ ARM ได้โดยตรง


1
Javaถูกคอมไพล์เป็นbytecodeซึ่งเป็นผู้ไม่เชื่อเรื่องพระเจ้าแพลตฟอร์มซึ่งสามารถดำเนินการโดย JVM ใด ๆ (ในทางทฤษฎีอย่างน้อย) บนแพลตฟอร์มใด ๆ C ถูกคอมไพล์เป็นภาษาแอสเซมบลีสำหรับ CPU ใดก็ตามที่คุณกำหนดเป้าหมาย (ดังนั้นหากคุณกำหนดเป้าหมายสถาปัตยกรรม x86 คอมไพเลอร์ C จะสร้างแอสเซมเบลอร์ x86 หรือแอสเซมเบลอร์ amd64 หากคุณกำหนดเป้าหมายสถาปัตยกรรมนั้น จากนั้นภาษาแอสเซมบลีจะถูกเปลี่ยนเป็นไฟล์ออบเจ็กต์ (แอสเซมบลีไบนารี่จริงๆ) ซึ่งเชื่อมโยงไปยังไฟล์ที่ใช้งานได้ (หลายรูปแบบที่แตกต่างกันขึ้นอยู่กับเครื่องเป้าหมาย)
Craig

1
ไม่มีสิ่งใดในข้อกำหนดภาษา Java ที่บอกอะไรเกี่ยวกับ JVM และอันที่จริงมีการใช้งาน Java โดยไม่มี JVM บน Android โปรแกรม Java ทำงานบน Dalvik VM (ล้าสมัยแล้ว) หรือ Android Runtime มีการใช้งาน Java สำหรับ CLI การใช้งานที่คอมไพล์กับ ECMAScript และการใช้งานที่คอมไพล์เป็นรหัสเนทีฟ มีคอมไพเลอร์ C ที่คอมไพล์ไปที่ JVM มีคอมไพเลอร์ C ที่คอมไพล์ไปที่ ECMAScript มีล่าม C
Jörg W Mittag
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.