Làm thế nào trình biên dịch C ++ đầu tiên có thể được viết bằng C ++?


48

Stroustrup tuyên bố rằng Cfront, trình biên dịch C ++ đầu tiên, được viết bằng C ++ ( Stroustrup FAQ ).

Tuy nhiên, làm thế nào thậm chí có khả năng trình biên dịch C ++ đầu tiên được viết bằng C ++?

Mã tạo nên trình biên dịch cũng cần phải được biên dịch, và do đó trình biên dịch C ++ đầu tiên không thể được viết bằng C ++, phải không?


6
vi.wikipedia.org/wiki/Cfront bao gồm vấn đề một chút.
christofr

Câu trả lời:


57

Chìa khóa ở ngay đây:

Trình biên dịch C ++ đầu tiên (Cfront) được viết bằng C ++. Để xây dựng điều đó, trước tiên tôi sử dụng C để viết bộ tiền xử lý "C với các lớp" -to-C. "C with Classes" là một phương ngữ C đã trở thành tổ tiên ngay lập tức của C ++. Bộ tiền xử lý đó đã dịch các cấu trúc "C with Classes" (chẳng hạn như các lớp và hàm tạo) thành C. Đó là một bộ tiền xử lý truyền thống không hiểu tất cả ngôn ngữ, khiến hầu hết các loại kiểm tra trình biên dịch C phải làm và dịch riêng lẻ xây dựng mà không có kiến ​​thức đầy đủ. Sau đó tôi đã viết phiên bản đầu tiên của Cfront trong "C with Classes".

Vì vậy, phiên bản đầu tiên của Cfront không được viết bằng C ++, thay vào đó là ngôn ngữ trung gian. Khả năng tạo trình biên dịch C và bộ tiền xử lý trực tiếp trong C đã dẫn đến nhiều cải tiến (và lỗ hổng bảo mật lớn ) trong C. Vì vậy, bạn viết trình soạn thảo mới để biến mã "C với Classes" thành C thẳng (vì C thẳng có thể làm được bất cứ điều gì) và sau đó bạn sử dụng "C with Classes" để viết trình biên dịch C ++ (không phải là bạn không thể làm điều đó trong C, chỉ mất một lúc) và sau đó bạn sử dụng trình biên dịch C ++ đó để viết một trình biên dịch hoàn chỉnh / hiệu quả hơn trong C ++. Hiểu rồi?


5
+1 để bao gồm một liên kết đến một trong những câu chuyện yêu thích của tôi về những điều có thể được thực hiện (và không nên).
jwernerny

3
Trình biên dịch được viết bằng mã C ++ hợp lệ, nhưng chỉ sử dụng một vài tính năng đầy đủ của C ++, những tính năng được hỗ trợ bởi bộ tiền xử lý "C with Classes". Nó đã sử dụng một tập hợp con của ngôn ngữ đầy đủ, do đó, nó cũng được biên dịch dựa trên kết quả (phiên bản làm việc đầu tiên của Cfront). Sau khi thực hiện bước "bootstrap" này, có lẽ anh ta không bao giờ cần phải sử dụng bộ tiền xử lý nữa.
joeytwiddle

2
@jwernerny - Tôi luôn thấy bài viết đó không thỏa mãn. Anh ta nhấn mạnh vào phần khó nhất và không tầm thường: "Lỗi sẽ khớp mã trong lệnh 'đăng nhập' UNIX. Mã thay thế sẽ trộn lẫn lệnh đăng nhập để nó chấp nhận mật khẩu được mã hóa dự định hoặc mật khẩu đã biết cụ thể. " Nhưng làm thế nào điều này sẽ được thực hiện? Nó đã bao giờ thực sự được chứng minh?
gièm pha

3
"đã dẫn đến nhiều đổi mới (và lỗ hổng bảo mật lớn) trong C": Theo tôi biết các thủ thuật này có thể được sử dụng trong bất kỳ ngôn ngữ nào, không chỉ trong C. Vì vậy, bất kỳ ngôn ngữ nào khác cũng có thể có cùng lỗ hổng bảo mật.
Giorgio

2
@detly: Nghe có vẻ tầm thường, nhưng vào năm 1983, đây là một cuộc tấn công mới lạ được thực hiện bởi sự thiếu đa dạng thực hiện. Chúng tôi đã tin tưởng nhiều hơn vào các nhị phân hồi đó, một phần vì việc biên dịch mọi thứ từ nguồn là một thử thách lớn hơn nhiều so với bây giờ.
Blrfl

17

Nó đã được bootstrapping. Ngay khi một tính năng C ++ được thêm vào cfront, thì cfront cũng có thể sử dụng tính năng đó từ thời điểm đó (nhưng không thực hiện chính tính năng đó). Điều này hoạt động vì cfront có khả năng chuyển đổi mã C ++ thành mã C. Vì vậy, nếu một số nền tảng mới xuất hiện, bạn có thể sử dụng cfront trên nền tảng khác để chuyển đổi cfront từ C ++ sang C, sau đó sử dụng trình biên dịch C của nền tảng mới để hoàn tất quá trình biên dịch từ C sang mã đối tượng.


9

Tôi nghĩ BS trả lời câu hỏi đó:

Trình biên dịch C ++ đầu tiên (Cfront) được viết bằng C ++. Để xây dựng điều đó, trước tiên tôi sử dụng C để viết bộ tiền xử lý "C với các lớp" -to-C. "C with Classes" là một phương ngữ C đã trở thành tổ tiên ngay lập tức của C ++. Bộ tiền xử lý đó đã dịch các cấu trúc "C with Classes" (chẳng hạn như các lớp và hàm tạo) thành C. Đó là một bộ tiền xử lý truyền thống không hiểu tất cả ngôn ngữ, khiến hầu hết các loại kiểm tra trình biên dịch C phải làm và dịch riêng lẻ xây dựng mà không có kiến ​​thức đầy đủ.

Sau đó tôi đã viết phiên bản đầu tiên của Cfront trong "C with Classes". Cfront là một trình biên dịch truyền thống đã hoàn thành cú pháp và kiểm tra ngữ nghĩa của nguồn C ++. Do đó, nó đã có một trình phân tích cú pháp hoàn chỉnh, xây dựng các bảng biểu tượng và xây dựng một biểu diễn cây bên trong hoàn chỉnh của từng lớp, hàm, v.v. Nó cũng đã thực hiện một số tối ưu hóa mức nguồn trên biểu diễn cây nội bộ của các cấu trúc C ++ trước khi xuất ra C. Phiên bản đó tạo C, không dựa vào C để kiểm tra loại nào. Nó chỉ đơn giản là sử dụng C như là một trình biên dịch. Mã kết quả là nhanh chóng không khoan nhượng.

Đầu tiên anh ta tạo ra thứ mà anh ta gọi là "C with Classes" được triển khai bởi một bộ tiền xử lý đơn giản thành C. Nó cơ bản là C ++, nhưng bộ tiền xử lý đã làm rất ít hoặc không kiểm tra. Sau đó, ông đã sử dụng nó để viết Cfront, phiên bản mạnh mẽ hơn của trình dịch C ++ sang C, hoàn thành với kiểm tra kiểu, bảng biểu tượng, v.v.


1
Vì vậy, về cơ bản khi chúng ta biên dịch một chương trình C ++, nó sẽ được chuyển đổi thành C, sau đó sau khi nó được chuyển đổi thành C, nó có được biên dịch lại thành mã máy không?
Pacerier

@Pacerier: Ban đầu, có, nhưng bây giờ tôi không nghĩ vậy.
Mike Dunlavey

tôi không hiểu bình luận của bạn Bạn có nghĩa là bây giờ có các trình biên dịch bỏ qua bước thứ hai và chỉ cần lấy nguồn C ++ và biên dịch thành mã máy?
Pacerier

7
@Pacerier: Chà, họ không trực tiếp đến ngôn ngữ lắp ráp hoặc mã máy. Thông thường trước tiên họ đi đến một đại diện trung gian độc lập với máy (bộ ba hoặc bộ tứ) và phân tích để tối ưu hóa. Từ đó họ tạo ra lắp ráp hoặc mã máy. Nếu bạn chọn một cuốn sách về thiết kế trình biên dịch (Aho & Ullman) tôi chắc chắn bạn sẽ thấy nó thú vị.
Mike Dunlavey

1
Điều quan trọng cần lưu ý là C ++ mà anh ta đang xây dựng cũng là một phần của ngôn ngữ hiện tồn tại. Nó không có mẫu, không có thư viện mới, chỉ sử dụng truyền C và nếu tôi nhớ lại chính xác, không có ngoại lệ.
Gort Robot

2

Tôi sẽ thêm câu trả lời này vì không có câu trả lời nào đề cập đến khía cạnh này.

Về mặt kỹ thuật, bạn không cần phần mềm để biên dịch mã. Miễn là bạn có các thông số kỹ thuật của trình biên dịch cần thiết, bạn có thể thực hiện việc biên dịch thực tế theo cách thủ công. Đây không phải là cách trình biên dịch C ++ đầu tiên được biên dịch. Tôi chỉ nói rằng nó có thể.

So sánh với ngôn ngữ lắp ráp. Khi chúng được sử dụng trong những ngày đầu, không có phần mềm biên dịch để chuyển đổi mã lắp ráp thành mã máy. Nó được thực hiện bằng tay, nhưng ngôn ngữ lắp ráp đã cho các lập trình viên một cái nhìn tổng quan tốt hơn.

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.