Điều gì ngăn C được biên dịch / giải thích / JIT'ed?


9

Java thường được ca ngợi vì tính di động tuyệt vời của nó, mà tôi đoán là do JVM. Câu hỏi của tôi là điều gì ngăn C được biên dịch / giải thích / JIT'ed .., nếu vậy, C cũng có thể được viết một lần và để nó hoạt động trên bất kỳ thiết bị nào bạn có. nhưng đây không phải là một cơ chế phổ biến để xử lý chương trình C.

Những nhược điểm của việc xử lý C theo cách này là gì, cũng có những ưu điểm nào khi xử lý Java theo cách này và không biên dịch thành mã máy, ngoài khả năng là tính di động?


Câu hỏi của bạn đã có một số câu trả lời rất hay ở đây: stackoverflow.com/questions/3925947/ Khăn
Doc Brown

2
@delnan quan điểm của tôi là "điều gì ngăn C được biên dịch / giải thích / JIT'ed" thực sự mất đi ý nghĩa của nó khi ngôn ngữ có thể nhắm mục tiêu vào một máy ảo có JIT hoặc các tình huống mà vm sẽ xác định các tính năng bị thiếu trong phần cứng và biên dịch lại mã để phù hợp với phần cứng hiện có (như với OpenGL (được viết bằng C) trên OSX cho các card đồ họa khác nhau). Không, bạn không thể lấy một cái gì đó được biên dịch để nhắm mục tiêu llvm trên một máy và chạy nó như vậy trên bộ xử lý khác. Nhưng dòng biên dịch / giải thích / JIT có thể khá mờ.

1
Java thường được thổi phồng cho tính di động tuyệt vời của nó. Nó có thể di chuyển tới các hệ thống đã biên dịch JVM, nghĩa là các hệ thống mà JVM (được viết bằng C) đã được biên dịch. Không có gì ngăn cản việc xử lý mã C theo cùng một cách, ngoại trừ việc không ai thấy đủ lợi ích từ việc làm điều đó để biện minh cho nỗ lực này.
Pete Becker

2
Tôi hoang mang về bit này: "điều gì ngăn C được biên dịch / [...]". À, không có gì?
Andres F.

1
Trình biên dịch C khá nhanh trong những ngày này vì vậy "make myprog.c; myprog" có thể sẽ chạy nhanh hơn hầu hết các trình thông dịch.
James Anderson

Câu trả lời:


18

C là những gì tôi sẽ gọi là một ngôn ngữ trung cấp. Mục đích của nó là phục vụ như một "trình biên dịch cấp độ rất cao", đó là lý do tại sao nó hoạt động tốt như một mục tiêu của trình biên dịch và tại sao nó nắm bắt được tính di động rất tốt.

Trong lịch sử, thông dịch viên thường được sử dụng với các ngôn ngữ cấp cao, trong bối cảnh các cuộc gọi phương thức. Ở dạng đơn giản nhất, một trình thông dịch chỉ phân tích cú pháp từng từ khóa trong ngôn ngữ nguồn cùng với các mã thông báo được liên kết của nó và chuyển đổi nó thành các lệnh gọi và tham số của phương thức. Trong thực tế, những gì hầu hết các thông dịch viên làm là chuyển đổi ngôn ngữ nguồn thành một số biểu diễn trung gian và chính đại diện đó được diễn giải.

Điều gì ngăn C không được giải thích hoặc Jited? Không có gì. Nhưng đó không phải là tù nhân của C.


6

Trước hết, đáng chú ý là JVM của Sun được viết bằng C. C là ngôn ngữ rất phổ biến khi cần tính di động.

Ngôn ngữ C có thể mang theo được mặc dù nhiều chương trình C không có. Điều này là do C không đặt ra nhiều hạn chế đối với người lập trình hoặc đưa ra nhiều giả định. Nếu một lập trình viên C muốn các chương trình của mình có thể mang theo được, anh ta phải tự đặt ra những hạn chế đó.

Trong thực tế, điều đó thực sự không khó hơn nhiều so với việc sống với các hạn chế mà Java buộc bạn. Đây chủ yếu là vấn đề quan tâm đến tính bền vững và kích thước nguyên thủy của bạn và sử dụng các thư viện di động như GTK + thay vì các thư viện dành riêng cho nền tảng.

Bạn có thể tạo một trình biên dịch GTK + đích và C hỗ trợ một máy ảo, thậm chí có thể là JVM và để mã hiện có hoạt động với rất ít thay đổi. Trong thực tế, nếu không có bộ sưu tập rác, một máy ảo C có lẽ sẽ đơn giản hơn nhiều. Tại sao bạn muốn, mặc dù?

Việc đảo ngược, biên dịch Java thành mã gốc, cũng có thể thực hiện được. Về cơ bản đó là những gì JIT làm. Tại sao bạn muốn, mặc dù? Tôi chắc chắn có những dự án thú cưng để làm điều đó "chỉ vì", nhưng chúng không được sử dụng nghiêm túc.


5

Bạn đã nói:

Java thường được ca ngợi vì tính di động tuyệt vời của nó, mà tôi đoán là do JVM.

Và ở đó, trong câu đầu tiên, bạn đã sai. Java không khả dụng vì JVM. Java có thể mang theo được, bởi vì ngôn ngữ Java được định nghĩa theo cách không khiến người thực hiện bất kỳ sự chậm trễ nào trong cách chương trình có thể hoạt động.

Ví dụ, Java có hai loại "int" (số nguyên 32 bit đã ký) và "dài" (số nguyên 64 bit đã ký). C và C ++ có "int" (ký ít nhất 16 bit), "dài" (ký ít nhất 32 bit) và "dài dài" (ký ít nhất 64 bit). Đó là bởi vì C được cho là chạy trên nhiều bộ xử lý khác nhau và cho phép chúng hoạt động khác nhau.

C có thể đã xác định kích thước cố định cho các loại này. Nếu có, bộ xử lý 36 bit không thể thực hiện ngôn ngữ C. Và họ thực sự không thể thực hiện Java! Vì vậy, C cho phép ngôn ngữ làm việc với nhiều loại máy tính khác nhau. Điều này là không thể tránh khỏi rằng điều này cho phép tạo mã không khả chuyển. Đó là một vấn đề của ngôn ngữ.


Có thể mô phỏng số học 32 bit trên máy 36 bit VÀ kết quả của mọi hoạt động với 0xFFFFFFFF để cắt nó thành 32 bit. Vì vậy, các máy này có thể triển khai Java, nó sẽ chậm hơn so với nếu Java cho phép các loại không dựa trên.
dan04

4

Java có tính di động cao đặc biệt vì ngôn ngữ nhắm vào Máy ảo Java, đúng như tên gọi của nó, không phải là một máy thật . Vì bạn có thể triển khai Máy ảo trên kiến ​​trúc của nhiều loại máy thật khác nhau, nên một chương trình dựa trên JVM có tính di động cao.

Mặt khác, C được thiết kế đặc biệt để chạy trên phần cứng thực, bởi vì nó được tạo ra cho mục đích cụ thể để thực hiện một hệ điều hành, cần truy cập đầy đủ phần cứng. Điều này có nghĩa là mã C không đặc biệt di động theo thiết kế và khi chuyển một chương trình C từ nền tảng này sang nền tảng khác, các phần khác nhau dành riêng cho kiến ​​trúc đích sẽ cần phải được viết lại ở mức độ này hay mức độ khác.


7
C có tính di động cao. Bạn chỉ cần biên dịch lại trên nền tảng đích và tránh một vài bit cụ thể và cố ý không mang theo được.
Robert Harvey

5
@RobertHarvey: ... chẳng hạn như những thứ cơ bản như kích thước của các nguyên thủy khác nhau? ;)
Mason Wheeler

2
Vâng, những điều đó. Thật không may là vấn đề tồn tại, nhưng ngôn ngữ hoàn toàn có thể di chuyển theo mọi cách khác nhau và có nhiều cách để đảm bảo rằng kích thước nguyên thủy hoạt động trên tất cả các nền tảng.
Robert Harvey

3
@RobertHarvey: Tôi sẽ nói C làm cho nó có thể viết các chương trình di động, nhưng nó không làm cho nó dễ dàng.
Doc Brown

2
@RobertHarvey: bạn có muốn bắt đầu một cuộc chiến tôn giáo không? ;-) Ngôn ngữ di động yêu thích của tôi là Python.
Doc Brown

3

Thực tế có các phiên bản C được giải thích , nhưng chúng chủ yếu được sử dụng để thử nghiệm nhanh hơn là hệ thống sản xuất.

Chúng không phổ biến, bởi vì sau tất cả, tại sao bạn phải chịu đựng tất cả các đặc điểm riêng của C nếu không có được một thực thi nhỏ, nhanh và tĩnh?


3

Về mặt lý thuyết cả C và Java đều có thể được biên dịch thành mã gốc, được giải thích hoặc biên dịch thành máy ảo.

Lý do kỹ thuật mà C không được biên dịch thành máy ảo, đơn giản là không có máy C ảo tiêu chuẩn .

Và dường như không ai muốn định nghĩa một máy C ảo, hoặc thậm chí biên dịch sang máy ảo Java (điều này là hoàn toàn có thể). Có lẽ bởi vì không ai sử dụng C muốn giảm tốc độ vô song của nó. Có lẽ cũng bởi vì C mạnh nhất trong cộng đồng nguồn mở có thể dễ dàng thực hiện tính di động bằng cách biên dịch (phân phối và biên dịch lại nguồn và thực thi), vì vậy họ không cảm thấy cần phải có tính di động (phân phối và thực thi nhị phân) như một đóng nhà phát triển nguồn làm.


1

Trên thực tế, điều này được thực hiện. Có các trình biên dịch chính hỗ trợ biên dịch cho LLVM (tôi biết clang cũng vậy và tôi tin rằng gcc cũng vậy). LLVM đó có thể là JIT'd giống như mã Java được biên dịch thành mã byte, đó là JIT'd.

Tuy nhiên, điều làm cho java "đa nền tảng" so với C là Java có một thư viện thời gian chạy lớn đã được chuyển sang nhiều nền tảng. C rõ ràng không theo mô hình này.


C với POSIX có thể khá di động (với bất kỳ hệ thống POSIX nào), nếu bạn cẩn thận viết mã.
Basile Starynkevitch

0

Có một số khác biệt chính giữa Java và C. Java được tách biệt khỏi hệ điều hành thông qua máy ảo java (JVM). JVM trừu tượng hóa hệ điều hành ra khỏi chương trình. Một ứng dụng java có thể yêu cầu JVM cho một đoạn bộ nhớ và JVM sau đó yêu cầu HĐH cho bộ nhớ đó. Có nhiều JVM cho các nền tảng / hệ điều hành khác nhau. JVM là thứ cho phép cùng một chương trình java chạy trên các nền tảng khác nhau.

Với C, không có sự cô lập hệ điều hành. Các chương trình C (thường) chạy trực tiếp trên hệ điều hành, thực hiện các cuộc gọi hệ điều hành trực tiếp. Điều này làm cho mối quan hệ mà chương trình C với một hệ điều hành / nền tảng cụ thể. Bất kỳ chương trình không tầm thường nào cũng sẽ thực hiện các cuộc gọi vào hệ điều hành. Ngoài ra, các chương trình C được biên dịch thành mã máy, là phần cứng cụ thể. Một chương trình C được biên dịch cho x86 không thể chạy trực tiếp trên bộ xử lý ARM.


1
Java được biên dịch thành mã byte bất khả tri của nền tảng , có thể (về mặt lý thuyết, ít nhất là) được thực thi bởi bất kỳ JVM nào trên bất kỳ nền tảng nào. C được biên dịch thành ngôn ngữ lắp ráp cho bất kỳ CPU nào bạn đang nhắm mục tiêu (vì vậy nếu bạn đang nhắm mục tiêu kiến ​​trúc x86, trình biên dịch C sẽ tạo trình biên dịch x86 hoặc trình biên dịch amd64 nếu bạn nhắm mục tiêu kiến ​​trúc đó hoặc trình biên dịch ARM, v.v.). Sau đó, ngôn ngữ lắp ráp được biến thành các tệp đối tượng (trình biên dịch nhị phân, thực sự), được liên kết thành một tệp thực thi (một số định dạng khác nhau, tùy thuộc vào máy đích).
Craig

1
Không có gì trong Đặc tả ngôn ngữ Java nói bất cứ điều gì về JVM và trên thực tế, có các triển khai Java mà không có JVM. Trên Android, các chương trình Java chạy trên Dalvik VM (hiện đã lỗi thời) hoặc Android Runtime, có các triển khai Java cho CLI, các triển khai biên dịch thành ECMAScript và các triển khai biên dịch thành mã gốc. Có các trình biên dịch C biên dịch thành JVM. Có trình biên dịch C biên dịch thành ECMAScript. Có C phiên dịch.
Jörg W Mittag
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.