Tại sao lập trình C cần một trình biên dịch và shell script không?


8

Tôi đã viết một tập lệnh bash và tôi đã thực hiện nó mà không cần biên dịch nó trước. Nó hoạt động hoàn hảo. Nó có thể hoạt động với hoặc không có quyền, nhưng khi nói đến các chương trình C, chúng ta cần biên dịch mã nguồn. Tại sao?


9
Nó có nghĩa là C là một ngôn ngữ được biên dịch và Bash là một ngôn ngữ được giải thích. Không hơn không kém.
Radon Rosborough

10
Tôi đang bỏ phiếu để đóng câu hỏi này ngoài chủ đề vì nó không liên quan đến U & L, và ngay cả khi nó là, nó quá rộng vì người ta có thể thảo luận không ngừng mà không đưa ra câu trả lời thỏa mãn, không nói về câu trả lời phù hợp với ý tưởng chung về U & L là cơ sở tri thức để giải quyết vấn đề.
phản ứng

4
@countmode Bạn xếp chồng (trao đổi | tràn) folks và phiếu bầu gần như kích hoạt hạnh phúc của bạn. Câu hỏi không rộng: nó cho thấy một phần thiếu hiểu biết rất cụ thể: sự khác biệt giữa các ngôn ngữ được biên dịch và giải thích. Điều này cần một vài đoạn để giải thích, và một vài đoạn khác để chỉ ra (các) ưu điểm của mỗi đoạn, cộng với một chú thích để tóm tắt rằng C và bash có các mục tiêu khác nhau, do đó họ chọn các cách tiếp cận khác nhau.
mtraceur

2
@mtraceur Xin lỗi, tôi không có ý xúc phạm bất cứ ai. Theo phiếu bầu kích hoạt hạnh phúc, điều này hơi bất công. Cần có năm phiếu để đóng một câu hỏi và nếu có ai khác bỏ phiếu không đóng thì tôi sẽ ổn với nó. Bạn hoàn toàn đúng về câu hỏi, nhưng tôi không chắc liệu những câu hỏi đó có thuộc về U & L hay không theo unix.stackexchange.com/help/on-topic .
phản ứng

2
@mtraceur nếu bạn nghĩ nó không rộng, tôi không đồng ý với bạn. Có nhiều điều để nói về sự khác biệt giữa trình biên dịch / trình thông dịch / v.v. và giải thích / biên dịch ngôn ngữ. Có caevats rất dễ trúng. Hơn nữa, câu hỏi phù hợp với "Khoa học máy tính" hoặc "Lập trình viên" SE tốt hơn.
MatthewRock

Câu trả lời:


23

Điều đó có nghĩa là các tập lệnh shell không được biên dịch, chúng được diễn giải: shell diễn giải các tập lệnh một lệnh tại một thời điểm và tìm ra mỗi lần cách thực hiện mỗi lệnh. Điều đó có ý nghĩa đối với các kịch bản shell vì dù sao họ cũng dành phần lớn thời gian để chạy các chương trình khác.

Mặt khác, các chương trình C thường được biên dịch: trước khi chúng có thể được chạy, một trình biên dịch sẽ chuyển đổi chúng thành toàn bộ mã máy, một lần và mãi mãi. Trước đây đã có người phiên dịch C (như người phiên dịch C của HiSoft trên Atari ST) nhưng họ rất bất thường. Ngày nay trình biên dịch C rất nhanh; TCC nhanh đến mức bạn có thể sử dụng nó để tạo "tập lệnh C", với #!/usr/bin/tcc -runshebang, vì vậy bạn có thể tạo chương trình C chạy giống như tập lệnh shell (theo quan điểm của người dùng).

Một số ngôn ngữ thường có cả trình thông dịch và trình biên dịch: BASIC là một ví dụ gây chú ý.

Bạn cũng có thể tìm thấy cái gọi là trình biên dịch shell shell nhưng những cái tôi đã thấy chỉ là các trình bao bọc che giấu: chúng vẫn sử dụng shell để thực sự diễn giải kịch bản. Như mtraceur chỉ ra mặc dù trình biên dịch shell shell thích hợp chắc chắn là có thể, chỉ là không thú vị lắm.

Một cách nghĩ khác về điều này là xem xét rằng khả năng diễn giải kịch bản của shell là một phần mở rộng của khả năng xử lý dòng lệnh của nó, điều này dẫn đến một cách tiếp cận được diễn giải. Mặt khác, C được thiết kế để tạo ra các nhị phân độc lập; điều này dẫn đến một cách tiếp cận tổng hợp. Các ngôn ngữ thường được biên dịch cũng có xu hướng mọc lên các trình thông dịch, hoặc ít nhất là các trình phân tích cú pháp dòng lệnh (được gọi là REPL, các vòng lặp đọc-in ; bản thân vỏ là REPL).


1
Nhiều "trình biên dịch" cho các ngôn ngữ scripting chỉ là các hàm bao. Tôi nhớ một trình biên dịch BASIC sẽ ghép nối trình thông dịch thực thi với mã nguồn được nén.
Dmitry Grigoryev

@DmitryGrigoryev Tôi có thể dễ dàng tin điều đó! Đối với BASIC tôi đã nghĩ đến các trình biên dịch như Turbo Basic. Tôi nghĩ rằng đã có một số trình biên dịch thực sự cho các tệp BAT của DOS, nhưng tôi có thể bị nhầm! Ngoài ra còn có cách tiếp cận mã p phổ biến ...
Stephen Kitt

1
Lưu ý rằng trình biên dịch "true" cho shell là hoàn toàn có thể. Nó chỉ là không thường xứng đáng với nỗ lực / phức tạp, vì một biến thể ngây thơ sẽ chỉ sản xuất một chương trình mà thường gọi một bó execve, open, close, read, write, và pipesyscalls, xen kẽ với một số getenv, setenvvà các hoạt động nội bộ hashmap / mảng (cho các biến phi xuất khẩu ), v.v. Vỏ Bourne và các dẫn xuất cũng không phải là ngôn ngữ lập trình được hưởng lợi nhiều từ các chỉnh sửa trình biên dịch cấp thấp như sắp xếp lại mã, v.v.
mtraceur

@StephenKitt bạn có phiền không nếu tôi đưa ra một câu hỏi mới liên quan đến nhận xét câu trả lời của bạn. Mặc dù bạn trả lời giải thích rất nhiều. nhưng cũng đặt ra một câu hỏi mới cho tôi
Mongrel

Ya chắc chắn rõ ràng, tôi sẽ mở một câu hỏi mới. Tôi nghĩ bạn có thể muốn tôi hỏi nó khi trò chuyện. bởi vì nó liên quan đến câu trả lời của bạn
Mongrel

6

Hãy xem xét chương trình sau:

2 Mars Bars
2 Milks
1 Bread
1 Corn Flakes

Trên bashđường đi, bạn đi lang thang quanh cửa hàng để tìm các quán rượu, cuối cùng tìm thấy chúng, sau đó đi lang thang tìm sữa v.v ... Điều này hiệu quả bởi vì bạn đang chạy một chương trình phức tạp có tên "Người mua hàng có kinh nghiệm" có thể nhận ra bánh mì khi bạn nhìn thấy và tất cả các phức tạp khác của mua sắm. bashlà một chương trình khá phức tạp.

Ngoài ra, bạn có thể đưa danh sách mua sắm của bạn cho một trình biên dịch mua sắm. Trình biên dịch suy nghĩ một lúc và cung cấp cho bạn một danh sách mới. Danh sách này là DÀI , nhưng bao gồm nhiều hướng dẫn đơn giản hơn:

... lots of instructions on how to get to the store, get a shopping cart etc.
move west one aisle.
move north two sections.
move hand to shelf three.
grab object.
move hand to shopping cart.
release object.
... and so on and so forth.

Như bạn có thể thấy, trình biên dịch biết chính xác mọi thứ trong cửa hàng nên không cần đến toàn bộ giai đoạn "tìm kiếm mọi thứ".

Đây là một chương trình theo đúng nghĩa của nó và không cần "Người mua hàng có kinh nghiệm" để thực hiện. Tất cả những gì nó cần là một con người với "Hệ điều hành cơ bản của con người".

Quay trở lại các chương trình máy tính: bashlà "Người mua hàng có kinh nghiệm" và có thể lấy một tập lệnh và chỉ cần thực hiện nó mà không cần biên dịch bất cứ điều gì. Trình biên dịch AC tạo ra một chương trình độc lập không còn cần sự trợ giúp để chạy.

Cả phiên dịch viên và trình biên dịch đều có những ưu điểm và nhược điểm.


3
Tương tự đẹp ... cũng giải thích lý do tại sao bạn có thể sử dụng cùng một danh sách mua sắm nhưng không phải cùng mã máy trên một kiến ​​trúc khác (sic!) - tất cả nội dung đều ở các vị trí khác nhau, v.v. Bạn có thể cần một "người mua sắm có kinh nghiệm" khác Ai biết siêu thị khác nhau.
Peter - Tái lập Monica

6

Tất cả là do sự khác biệt về kỹ thuật giữa cách chương trình bạn có thể đọc / ghi khi con người được chuyển đổi thành máy hướng dẫn máy tính của bạn hiểu - và những ưu điểm và nhược điểm khác nhau của mỗi phương pháp là lý do tại sao một số ngôn ngữ được viết cần trình biên dịch và một số được viết để được giải thích.

Đầu tiên, sự khác biệt kỹ thuật

(Lưu ý: Tôi đơn giản hóa rất nhiều ở đây để giải quyết câu hỏi. Để hiểu sâu hơn, các ghi chú kỹ thuật ở cuối câu trả lời của tôi chi tiết / tinh chỉnh một số đơn giản hóa ở đây và nhận xét về câu trả lời này có một số làm rõ và thảo luận hữu ích là tốt ..)

Về cơ bản có hai loại ngôn ngữ lập trình chung:

  1. Một chương trình khác ("trình biên dịch") đọc chương trình của bạn, xác định các bước mà mã của bạn sẽ làm và sau đó viết một chương trình mới bằng mã máy ("ngôn ngữ" mà chính máy tính của bạn hiểu) thực hiện các bước đó.
  2. Một chương trình khác ("trình thông dịch") đọc chương trình của bạn, xác định các bước mà mã của bạn nói để làm và sau đó thực hiện các bước đó . Không có chương trình mới được tạo ra.

C nằm trong danh mục đầu tiên ( trình biên dịch C dịch ngôn ngữ C sang mã máy của máy tính của bạn : mã máy được lưu vào một tệp và sau đó khi bạn chạy mã máy đó, nó sẽ thực hiện những gì bạn muốn).

bash thuộc loại thứ hai (trình thông dịch bash đọc ngôn ngữ bash và trình thông dịch bash thực hiện những gì bạn muốn: vì vậy không có "mô-đun trình biên dịch" mỗi se, trình thông dịch thực hiện phiên dịch và thực thi, trong khi trình biên dịch đọc và dịch) .

Bạn có thể đã nhận thấy điều này có nghĩa là gì:

Với C, bạn thực hiện bước "phiên dịch" một lần , sau đó bất cứ khi nào bạn cần chạy chương trình, bạn chỉ cần nói với máy tính của mình thực thi mã máy - máy tính của bạn có thể chạy trực tiếp mà không cần phải thực hiện thêm "suy nghĩ" nào.

Với bash, bạn phải thực hiện bước "phiên dịch" mỗi khi bạn chạy chương trình - máy tính của bạn đang chạy trình thông dịch bash và trình thông dịch bash thực hiện thêm "suy nghĩ" để tìm ra những gì nó cần làm cho mỗi lệnh, mỗi lần .

Vì vậy, các chương trình C cần nhiều CPU, bộ nhớ và thời gian hơn để chuẩn bị (bước biên dịch) nhưng tốn ít thời gian và công sức hơn để chạy. các chương trình bash tốn ít CPU, bộ nhớ và thời gian để chuẩn bị, nhưng cần nhiều thời gian và công việc hơn để chạy. Bạn có thể không nhận thấy những khác biệt này hầu hết thời gian vì máy tính ngày nay rất nhanh, nhưng nó tạo ra sự khác biệt và sự khác biệt đó cộng lại khi bạn cần chạy các chương trình lớn hoặc phức tạp, hoặc nhiều chương trình nhỏ.

Ngoài ra, vì các chương trình C được chuyển đổi thành mã máy ("ngôn ngữ bản địa") của máy tính, bạn không thể lấy một chương trình và sao chép nó vào một máy tính khác có mã máy khác (ví dụ: Intel 64 bit vào Intel 32 -bit, hoặc từ Intel sang ARM hoặc MIPS hoặc bất cứ điều gì). Bạn phải dành thời gian để biên dịch nó cho ngôn ngữ máy khác đó một lần nữa . Nhưng một chương trình bash chỉ có thể được chuyển sang một máy tính khác có cài đặt trình thông dịch bash và nó sẽ chạy tốt.

Bây giờ tại sao một phần của câu hỏi của bạn

Các nhà sản xuất của C đã viết một hệ điều hành và các chương trình khác trên phần cứng từ nhiều thập kỷ trước, điều đó khá hạn chế bởi các tiêu chuẩn hiện đại. Vì nhiều lý do, chuyển đổi các chương trình thành mã máy của máy tính là cách tốt nhất hướng tới mục tiêu đó cho họ vào thời điểm đó. Thêm vào đó, họ đang thực hiện loại công việc mà điều quan trọng là mã họ viết đã chạy hiệu quả .

Và các nhà sản xuất shell Bourne và bash muốn ngược lại: Họ muốn viết các chương trình / lệnh có thể được thực thi ngay lập tức - trên dòng lệnh, trong một thiết bị đầu cuối, bạn muốn chỉ viết một dòng, một lệnh và có nó hành hình. Và họ muốn các tập lệnh mà bạn đã viết để làm việc ở bất cứ nơi nào bạn đã cài đặt trình thông dịch / chương trình shell.

Phần kết luận

Vì vậy, trong ngắn hạn, bạn không cần một trình biên dịch cho bash nhưng bạn cần một trình biên dịch cho C vì các ngôn ngữ đó được chuyển đổi thành các hành động máy tính thực tế khác nhau và những cách làm khác nhau đó được chọn vì các ngôn ngữ có mục tiêu khác nhau.

Các chi tiết / ghi chú kỹ thuật / nâng cao khác

  1. Bạn thực sự có thể tạo một trình thông dịch C hoặc trình biên dịch bash. Không có gì ngăn cản điều đó là có thể: đó chỉ là những ngôn ngữ được tạo ra cho các mục đích khác nhau. Việc viết lại chương trình bằng ngôn ngữ khác thường dễ hơn là viết một trình thông dịch hoặc trình biên dịch tốt cho một ngôn ngữ lập trình phức tạp. Đặc biệt là khi những ngôn ngữ đó có một điều cụ thể mà họ giỏi và được thiết kế với một cách làm việc nhất định ngay từ đầu. C được thiết kế để biên dịch, do đó, nó thiếu rất nhiều tốc ký tiện lợi mà bạn muốn trong một vỏ tương tác, nhưng nó rất tốt để thể hiện dữ liệu / bộ nhớ ở mức độ thấp rất cụ thể và tương tác với hệ điều hành , đó là những nhiệm vụ bạn thường thấy mình làm khi bạn muốn viết mã được biên dịch hiệu quả. Trong khi đó, bash rất giỏi trong việc thực hiện các chương trình khác,

  2. Chi tiết nâng cao hơn: Có những ngôn ngữ lập trình thực sự là sự pha trộn của cả hai loại (chúng dịch mã nguồn "hầu hết mọi cách", để chúng có thể thực hiện hầu hết việc diễn giải / "suy nghĩ" một lần và chỉ làm một chút của việc giải thích / "suy nghĩ" sau này). Java, Python và nhiều ngôn ngữ hiện đại khác thực sự là những hỗn hợp như vậy: chúng cố gắng mang lại cho bạn một số lợi ích về tính di động và / hoặc phát triển nhanh của các ngôn ngữ được dịch và một số tốc độ của ngôn ngữ được biên dịch. Có rất nhiều cách có thể để kết hợp các cách tiếp cận như vậy và các ngôn ngữ khác nhau thực hiện theo cách khác nhau. Nếu bạn muốn đi sâu vào chủ đề này, bạn có thể đọc các ngôn ngữ lập trình biên dịch thành "mã byte" (giống như biên dịch thành "ngôn ngữ máy" tự tạo của bạn

  3. Bạn đã hỏi về bit thực thi: thực ra, bit thực thi chỉ ở đó để báo cho hệ điều hành biết rằng tệp đó được phép thực thi. Tôi nghi ngờ rằng lý do duy nhất các tập lệnh bash hoạt động cho bạn mà không có sự cho phép thực thi là vì bạn đang chạy chúng từ bên trong một bash shell. Thông thường, hệ điều hành, khi được yêu cầu thực thi một tệp mà không thiết lập bit thực thi, sẽ chỉ trả về một lỗi. Nhưng một số shell như bash sẽ thấy lỗi đó và tự mình chạy nó để chạy tệp, bằng cách mô phỏng các bước mà hệ điều hành thường sẽ thực hiện (tra cứu dòng "#!" Ở đầu tệp và thử để thực thi chương trình đó để giải thích tệp, với mặc định là chính nó hoặc /bin/shnếu không có dòng "#!").

  4. Đôi khi một trình biên dịch đã được cài đặt trên hệ thống của bạn và đôi khi các IDE đi kèm với trình biên dịch riêng của chúng và / hoặc chạy trình biên dịch cho bạn. Điều này có thể làm cho một ngôn ngữ được biên dịch "cảm thấy" giống như một ngôn ngữ không được biên dịch để sử dụng, nhưng sự khác biệt về kỹ thuật vẫn còn đó.

  5. Một ngôn ngữ "được biên dịch" không nhất thiết phải được biên dịch thành mã máy và toàn bộ việc biên dịch đây là một chủ đề. Về cơ bản, thuật ngữ này được sử dụng rộng rãi: nó thực sự có thể đề cập đến một vài điều. Theo một nghĩa cụ thể, "trình biên dịch" chỉ là một trình dịch từ một ngôn ngữ (thường là ngôn ngữ "cấp cao hơn" dễ sử dụng hơn) sang ngôn ngữ khác (thường là ngôn ngữ "cấp thấp hơn" mà máy tính dễ sử dụng hơn - đôi khi, nhưng thực sự không thường xuyên, đây là mã máy). Ngoài ra, đôi khi khi mọi người nói "trình biên dịch", họ thực sự đang nói về nhiều chương trình làm việc cùng nhau (đối với trình biên dịch C điển hình, thực tế có bốn chương trình: "tiền xử lý", trình biên dịch, "trình biên dịch" và "trình biên dịch" liên kết ").


Tôi không hiểu tại sao câu hỏi này bị hạ thấp. Đó là một câu trả lời toàn diện ấn tượng cho một câu hỏi rộng và không rõ ràng.
Anthony Geoghegan

Trình biên dịch dịch một ngôn ngữ này sang ngôn ngữ khác. Nó không phải biên dịch sang ngôn ngữ máy. Bạn có thể có trình biên dịch mã byte. Trình biên dịch Java sang ASM, v.v ... Các nhà sản xuất của C không muốn hầu hết sức mạnh, họ muốn ngôn ngữ phù hợp với nhu cầu của họ. C có thể được giải thích ở một mức độ nào đó. Bash có thể được biên dịch - có shc . Việc ngôn ngữ có được biên dịch / giải thích hay không - hầu hết thời gian - phụ thuộc vào các công cụ bạn sử dụng, chứ không phải ngôn ngữ, mặc dù một số quy ước được tuân theo.
MatthewRock

@MatthewRock Tôi đã thêm một lưu ý kỹ thuật để giải quyết việc biên dịch thành thứ không nhất thiết phải là ngôn ngữ máy. Tôi cảm thấy ghi chú kỹ thuật đầu tiên của tôi đã bao gồm điều "C có thể được giải thích ... Bash có thể được biên dịch". Tôi có một ý tưởng về cách giải quyết vấn đề "các nhà sản xuất C không muốn có sức mạnh nhất", mặc dù tôi nghĩ khá rõ ràng họ đã thiết kế ngôn ngữ hiệu quả trên phần cứng họ đang sử dụng vào thời điểm đó (byte rỗng- Điều kết thúc chuỗi là một phần do thực tế là việc đó cho phép bạn sử dụng một đăng ký ít hơn khi lặp lại trên một chuỗi trên những điều đó, sau tất cả).
mtraceur

@MatthewRock (tiếp) Tôi nghĩ thật công bằng khi nói rằng các nhà sản xuất C không thực sự muốn có sức mạnh, nhưng họ muốn trừu tượng hóa công việc viết OS, đặc biệt là vào thời đó là hiệu quả của mã. Và đó là công việc mà nếu không họ sẽ được thực hiện trong trình biên dịch chương trình. Vì vậy, họ đã tạo ra một ngôn ngữ có liên quan chặt chẽ với mã máy được sử dụng bởi các máy PDP mà họ đang viết mã, ít nhất là một tác dụng phụ, nếu không phải là mục tiêu thiết kế đáng chú ý, cho vay hiệu quả trên nền tảng đó, ngay cả với trình biên dịch không tối ưu ngây thơ.
mtraceur

Họ sẽ không làm điều đó trong trình biên dịch chương trình. Họ có B . Cạm bẫy ở khắp mọi nơi, và câu hỏi không phải là chủ đề ở đây. Nhìn chung, câu trả lời có thể sẽ trả lời câu hỏi, nhưng vẫn có những chi tiết không chính xác.
MatthewRock

5

Ngôn ngữ lập trình / kịch bản có thể được biên dịch hoặc giải thích.

Các tệp thực thi được biên dịch luôn nhanh hơn và nhiều lỗi có thể được phát hiện trước khi thực thi.

Các ngôn ngữ được giải thích thường đơn giản hơn để viết và thích nghi ít nghiêm ngặt hơn các ngôn ngữ được biên dịch và không yêu cầu biên dịch giúp chúng dễ phân phối hơn.


1
Trong bash script, nó cũng báo lỗi khi được thực thi. nhưng chúng tôi không biên dịch nó.
Mongrel

30
luôn luôn là một từ nguy hiểm
Radon Rosborough

3
Tối ưu hóa Biên soạn CPython thường chậm hơn so với asm.js tối ưu hóa (một tập hợp con của JavaScript) là. Do đó, có một ví dụ về việc nó không nhanh hơn và do đó nó không "luôn luôn" nhanh hơn. Tuy nhiên, nó thường là nhiều, nhanh hơn nhiều.
wizzwizz4

2
Điều này không trả lời câu hỏi.
mathreadler

3
luôn luôn nhanh hơn là một tuyên bố táo bạo. Nhưng điều này đi quá nhiều vào sâu về lý thuyết trình biên dịch và phiên dịch (và định nghĩa).
Giacomo Catenazzi

3

Hãy tưởng tượng rằng tiếng Anh không phải là ngôn ngữ mẹ đẻ của bạn (điều đó có thể khá dễ dàng với bạn nếu tiếng Anh không phải là ngôn ngữ mẹ đẻ của bạn).

Có 3 cách bạn có thể đọc nó:

  1. (Giải thích) Khi bạn đọc, hãy dịch từng từ mỗi khi bạn nhìn thấy nó
  2. (Tối ưu hóa-Giải thích) Tìm các cụm từ phổ biến (chẳng hạn như "ngôn ngữ mẹ đẻ của bạn"), dịch chúng và viết chúng xuống. Sau đó, dịch từng từ - ngoại trừ các cụm từ bạn đã dịch
  3. (Biên dịch) Yêu cầu người khác dịch toàn bộ câu trả lời

Máy tính có "ngôn ngữ bản địa" gồm nhiều loại - sự kết hợp các hướng dẫn mà bộ xử lý hiểu và hướng dẫn mà hệ điều hành (ví dụ: Windows, Linux, OSX, v.v.) hiểu. Ngôn ngữ này không thể đọc được bởi con người.

Các ngôn ngữ script, như Bash, thường rơi vào loại 1 và 2. Chúng lấy một dòng tại một thời điểm, dịch dòng đó và chạy nó, sau đó chuyển sang dòng tiếp theo. Trên Mac và Linux, khá nhiều trình thông dịch khác nhau được cài đặt theo mặc định cho các ngôn ngữ khác nhau, chẳng hạn như Bash, Python và Perl. Trên Windows, bạn phải tự cài đặt chúng.

Nhiều ngôn ngữ kịch bản xử lý trước một chút - cố gắng tăng tốc độ thực thi bằng cách biên dịch các đoạn mã sẽ được chạy thường xuyên hoặc điều đó sẽ làm chậm ứng dụng. Một số thuật ngữ bạn có thể nghe về bao gồm biên dịch Ahead-of-time (AOT) hoặc Just-in-time (JIT).

Cuối cùng, các ngôn ngữ được biên dịch - như C - dịch toàn bộ chương trình trước khi bạn có thể chạy chúng. Điều này có lợi thế là bản dịch có thể được thực hiện trên một máy khác để thực thi, vì vậy khi bạn đưa chương trình cho người dùng, trong khi vẫn có thể có lỗi, một số loại lỗi có thể được xóa sạch. Giống như nếu bạn đưa cái này cho người dịch của bạn, và tôi đề cập đến cách garboola mizene resplunks, nó có thể trông giống tiếng Anh hợp lệ với bạn nhưng người dịch có thể nói với bạn rằng tôi đang nói chuyện vô nghĩa. Khi bạn chạy một chương trình được biên dịch, nó không cần một trình thông dịch - nó đã có trong ngôn ngữ mẹ đẻ của máy tính

Tuy nhiên, có một nhược điểm của ngôn ngữ được biên dịch: Tôi đã đề cập rằng máy tính có ngôn ngữ bản địa, bao gồm các tính năng từ phần cứng và hệ điều hành - tốt, nếu bạn biên dịch chương trình của mình trên Windows, bạn sẽ không mong đợi chương trình được biên dịch chạy trên máy Mac. Một số ngôn ngữ khắc phục điều này bằng cách biên dịch thành một loại ngôn ngữ nửa vời - hơi giống tiếng Anh Pidgin - theo cách đó, bạn có được lợi ích của ngôn ngữ được biên dịch, cũng như tăng tốc độ nhỏ, nhưng điều đó có nghĩa là bạn cần phải bó một trình thông dịch với mã của bạn (hoặc sử dụng một trình thông dịch đã được cài đặt).

Cuối cùng, IDE của bạn có thể đã biên dịch các tệp của bạn cho bạn và có thể cho bạn biết về các lỗi trước khi bạn chạy mã. Đôi khi, kiểm tra lỗi này có thể sâu hơn trình biên dịch sẽ làm. Một trình biên dịch thường sẽ chỉ kiểm tra nhiều như nó cần để nó có thể tạo ra mã gốc hợp lý. Một IDE thường sẽ chạy một vài kiểm tra bổ sung và có thể cho bạn biết, ví dụ, nếu bạn đã xác định một biến hai lần hoặc nếu bạn đã nhập một cái gì đó mà bạn chưa sử dụng.


Câu trả lời này rất hay, nhưng tôi nghĩ rằng phần tổng hợp động được sử dụng bởi "trình thông dịch" Perl khác với cái thường được gọi là "JIT", vì vậy có lẽ tốt nhất nên tránh thuật ngữ đó. JIT thường được sử dụng để chỉ việc biên dịch đúng lúc từ mã byte đã được biên dịch sang mã máy đích, ví dụ JVM, .Net CLR.
IMSoP

@IMSoP Vâng, các ngôn ngữ biên dịch byte và các ngôn ngữ mà JIT biên dịch từ mã byte, thực sự là những thứ khác nhau. Tôi nghĩ rằng nó có thể đáng được đề cập (tôi đã ghi một tham chiếu ngắn về nó trong phần chú thích của câu trả lời của tôi) nhưng ý tưởng chung mà JIT rơi vào mà tôi nghĩ là đáng để có một nơi nào đó ở giữa "được biên soạn" và "diễn giải", tức là được biên dịch một phần, và được giải thích một phần. Điều đó nói rằng, tôi không chắc rằng điều đó có giá trị hơn hay khó hiểu / gây mất tập trung cho một người chưa hiểu sự khác biệt giữa được biên dịch / giải thích, như OP.
mtraceur

@mtraceur Thành thật mà nói, ngay cả tôi cũng có một chút lạc lõng giữa sự khác biệt giữa các mô hình của, ví dụ, PHP 7, Perl 5, .Net và Java. Có lẽ tóm tắt tốt nhất cho người mới bắt đầu là "có nhiều cách khác nhau để biên dịch và biên dịch, bao gồm sử dụng một biểu diễn trung gian, và biên dịch hoặc biên dịch lại các đoạn khi chương trình được chạy".
IMSoP

@IMSoP Tôi đồng ý. Đó là cách tiếp cận mà tôi đã đưa ra trong câu trả lời của mình, và nhận xét này của bạn đã cho tôi một ý tưởng về cách tinh chỉnh điều đó hơn nữa. Cảm ơn.
mtraceur

@IMSoP JIT không chỉ xảy ra trên mã byte - ví dụ: node.js có một số tính năng JIT. Nhưng tôi đồng ý - Tôi đã gộp tất cả chúng dưới biểu ngữ "JIT" để đơn giản, vì điều này giống như một câu hỏi dành cho người mới bắt đầu - Tôi đang chỉnh sửa nó để sử dụng một thuật ngữ đơn giản hơn.
dùng208769

1

Rất nhiều người đang nói về giải thích so với biên dịch nhưng tôi nghĩ rằng điều này có thể gây hiểu lầm đôi chút nếu bạn nhìn kỹ vào nó vì một số ngôn ngữ được giải thích thực sự được biên dịch thành mã byte trung gian trước khi thực thi.

Cuối cùng, lý do thực sự khiến các chương trình C cần được biên dịch thành định dạng thực thi là máy tính cần thực hiện nhiều công việc để chuyển đổi mã trong tệp nguồn C thành một thứ gì đó có thể chạy để lưu sản phẩm một cách hợp lý của tất cả những gì hoạt động thành một tập tin thực thi, do đó bạn không cần phải làm lại mỗi lần bạn muốn chạy chương trình của mình.

Mặt khác, trình thông dịch Shell cần thực hiện rất ít công việc để chuyển đổi tập lệnh shell thành "hoạt động của máy". Về cơ bản chỉ cần đọc dòng script theo từng dòng, phân tách nó trên khoảng trắng, thiết lập một số chuyển hướng tập tin và đường ống và sau đó thực hiện một fork + exec. Do chi phí phân tích và xử lý đầu vào văn bản của tập lệnh shell rất nhỏ so với thời gian khởi chạy các quy trình trong tập lệnh shell, nên sẽ quá mức để biên dịch tập lệnh shell sang định dạng máy trung gian thay vì chỉ diễn giải mã nguồn trực tiếp.


+1, mặc dù tôi thấy mình băn khoăn không biết đây có phải là "đặt xe trước ngựa không": có lẽ các vỏ ban đầu được dự định có thể tương tác có thể sử dụng được và do đó đủ chi phí thấp để không bận tâm biên dịch, và sự đơn giản tương đối là chỉ là một quyết định thiết kế dựa trên đó?
mtraceur

Vâng, đó là một cách khác để xem xét câu hỏi này :)
hugomg
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.