Có phải ngôn ngữ lập trình C được coi là ngôn ngữ cấp thấp khi nó xuất hiện?


151

Hiện tại C được coi là ngôn ngữ cấp thấp , nhưng vào những năm 70, nó có được coi là ngôn ngữ cấp thấp không? Là thuật ngữ ngay cả trong sử dụng sau đó?

Nhiều ngôn ngữ cấp cao phổ biến đã không tồn tại cho đến giữa thập niên 80 và hơn thế nữa, vì vậy tôi tò mò liệu bản chất của cấp độ thấp đã thay đổi như thế nào trong những năm qua.


13
Là một điểm dữ liệu, khoảng năm 1978, một số cố vấn lập trình đã mô tả C với tôi như một ngôn ngữ lắp ráp được tôn vinh.
Ben Crowell

7
@BenCrowell Tôi không chắc chắn ý nghĩa của việc tôn vinh ý nghĩa trong bối cảnh tuyên bố của bạn nhưng tôi đã có kinh nghiệm gọi C là ngôn ngữ lắp ráp phổ biến (độc lập với nền tảng) .
Melebius

13
Điều thú vị là, có một trường hợp được thực hiện mà C không phải là một ngôn ngữ cấp thấp , và ít ngay bây giờ hơn là trong những năm 70, bởi vì máy trừu tượng C được xa hơn ra khỏi phần cứng hiện đại hơn đó là từ PDP-11.
Tom

5
Khi nghĩ về điều này, bạn cũng có thể muốn nghĩ về nguồn gốc - Unix được viết bằng C, c chạy trên Unix và biên dịch chéo unix sang các nền tảng khác. Bất cứ điều gì không cần thiết để biên dịch Unix là chi phí không cần thiết và mục tiêu chính của C là làm cho nó dễ dàng viết / chuyển trình biên dịch nhất có thể. Với mục đích này, đó là mức chính xác CHÍNH XÁC, vì vậy tôi không nghĩ C là cấp cao hay cấp thấp, tôi nghĩ nó là một công cụ để chuyển Unix, giống như hầu hết các công cụ Unix, cực kỳ thích ứng với nhiều vấn đề.
Bill K

4
Điều đáng chú ý là lisp đã được phát minh vào năm 1958
Prime

Câu trả lời:


144

Để trả lời các khía cạnh lịch sử của câu hỏi:

Triết lý thiết kế được giải thích trong Ngôn ngữ lập trình C được viết bởi Brian Kernighan và nhà thiết kế C Dennis Ritchie, "K & R" mà bạn có thể đã nghe nói đến. Lời nói đầu cho phiên bản đầu tiên nói

C không phải là ngôn ngữ "cấp độ rất cao", cũng không phải là ngôn ngữ "lớn" ...

và phần giới thiệu nói

C là ngôn ngữ tương đối "cấp thấp" ... C không cung cấp thao tác nào để xử lý trực tiếp các đối tượng tổng hợp như chuỗi ký tự, bộ, danh sách hoặc mảng. Không có thao tác nào thao túng toàn bộ một mảng hoặc chuỗi ...

Danh sách tiếp tục một lúc trước khi văn bản tiếp tục:

Mặc dù sự vắng mặt của một số tính năng này có vẻ như là một thiếu sót nghiêm trọng, ... giữ cho ngôn ngữ ở kích thước khiêm tốn có lợi ích thực sự.

(Tôi chỉ có phiên bản thứ hai từ năm 1988, nhưng nhận xét bên dưới cho biết rằng văn bản được trích dẫn là giống nhau trong phiên bản đầu tiên năm 1978.)

Vì vậy, vâng, thuật ngữ "mức cao" và "mức thấp" đã được sử dụng trước đó, nhưng C được thiết kế để nằm ở đâu đó trên phổ ở giữa. Có thể viết mã bằng C di động trên các nền tảng phần cứng và đó là tiêu chí chính cho việc liệu một ngôn ngữ có được coi là cấp cao vào thời điểm đó hay không. Tuy nhiên, C thiếu một số tính năng đặc trưng của ngôn ngữ cấp cao và đây là một quyết định thiết kế có lợi cho sự đơn giản.


42
Đây là một câu trả lời tuyệt vời! Bằng chứng lịch sử có thể kiểm chứng + lời khai của một diễn viên được thông báo rõ nhất về ý nghĩa của cấp độ thấp và cao trong giai đoạn mà OP đề cập. Nhân tiện, tôi xác nhận rằng các trích dẫn đã có trong phiên bản 1978.
Christophe

157

Điều này phụ thuộc vào định nghĩa của bạn về ngôn ngữ cấp cao và cấp thấp. Khi C được phát triển, bất cứ thứ gì có cấp độ cao hơn lắp ráp đều được coi là ngôn ngữ cấp cao. Đó là một thanh thấp để xóa. Sau đó, thuật ngữ này đã chuyển sang điểm mà ngày nay một số người sẽ coi ngay cả Java là ngôn ngữ cấp thấp.

Ngay cả trong bối cảnh ngôn ngữ cấp cao của thập niên 70, điều đáng nói là C khá thấp. Ngôn ngữ C về cơ bản là B cộng với một hệ thống loại đơn giản và B không khác gì một lớp cú pháp thủ tục / cấu trúc thuận tiện để lắp ráp. Bởi vì hệ thống loại là phù hợp với retro trên đầu của ngôn ngữ B chưa được đánh dấu, bạn vẫn có thể bỏ chú thích loại ở một số nơi và intsẽ được giả định.

C có ý thức bỏ đi các tính năng đắt tiền hoặc khó thực hiện đã được thiết lập tốt tại thời điểm đó, chẳng hạn như

  • quản lý bộ nhớ tự động
  • chức năng lồng nhau hoặc đóng cửa
  • OOP hoặc coroutines cơ bản
  • hệ thống loại biểu cảm hơn (ví dụ: loại giới hạn phạm vi, loại do người dùng xác định, chẳng hạn như loại bản ghi, gõ mạnh, mật)

C có một số tính năng thú vị:

  • hỗ trợ đệ quy (là kết quả của các biến tự động dựa trên ngăn xếp của nó, so với các ngôn ngữ nơi tất cả các biến có tuổi thọ toàn cầu)
  • con trỏ hàm
  • Các kiểu dữ liệu do người dùng định nghĩa (cấu trúc và kết hợp) đã được triển khai ngay sau khi phát hành lần đầu của C.
  • Biểu diễn chuỗi của C (con trỏ tới ký tự) thực sự là một cải tiến lớn so với B, mã hóa nhiều chữ cái thành một từ máy.
  • Các tệp tiêu đề của C là một hack hiệu quả để giữ cho các đơn vị biên dịch nhỏ, nhưng cũng xảy ra để cung cấp một hệ thống mô-đun đơn giản.
  • Con trỏ không giới hạn kiểu con số và số học con trỏ, so với các tài liệu tham khảo an toàn hơn. Con trỏ vốn là một tính năng không an toàn nhưng cũng rất hữu ích cho lập trình cấp thấp.

Vào thời điểm C được phát triển, các ngôn ngữ cải tiến khác như COBOL, Lisp, ALGOL (theo nhiều phương ngữ khác nhau), PL / I, SNOBOL, Simula và Pascal đã được xuất bản và / hoặc được sử dụng rộng rãi cho các lĩnh vực vấn đề cụ thể. Nhưng hầu hết các ngôn ngữ hiện có được dành cho lập trình máy tính lớn, hoặc là các dự án nghiên cứu học thuật. Ví dụ, khi ALGOL-60 lần đầu tiên được thiết kế như một ngôn ngữ lập trình phổ quát, công nghệ máy tính và khoa học máy tính cần thiết để thực hiện nó chưa tồn tại. Một số trong số này (một số phương ngữ ALGOL, PL / I, Pascal) cũng được dành cho lập trình cấp thấp, nhưng chúng có xu hướng có trình biên dịch phức tạp hơn hoặc quá an toàn (ví dụ: không có con trỏ không bị hạn chế). Pascal đáng chú ý là thiếu hỗ trợ tốt cho các mảng có độ dài thay đổi.

So với các ngôn ngữ đó, C từ chối tính năng thanh lịch và các tính năng đắt tiền để thực tế hơn cho phát triển cấp thấp. C chưa bao giờ chủ yếu là một dự án nghiên cứu thiết kế ngôn ngữ. Thay vào đó, nó là một nhánh nhỏ của sự phát triển nhân Unix trên máy tính mini PDP-11 bị hạn chế về tài nguyên. Đối với sở trường của nó (một ngôn ngữ cấp thấp tối giản để viết Unix với trình biên dịch một lần dễ dàng chuyển) C hoàn toàn xuất sắc - và hơn 45 năm sau, nó vẫn là ngôn ngữ lập trình hệ thống.


17
Chỉ là một bổ sung nhỏ cho những người không biết về những gì cần thiết cho họ ALGOL và các ngôn ngữ Pascal hiện có: Những ngôn ngữ đó có các hàm lồng nhau theo ngôn ngữ nơi bạn có thể truy cập biến (cục bộ) được khai báo ở các hàm ngoài. Điều đó có nghĩa là bạn phải duy trì "màn hình" - một loạt các con trỏ tới các phạm vi từ vựng bên ngoài - tại mỗi lần gọi và trả về hàm (đã thay đổi cấp độ từ vựng) - hoặc bạn phải xâu chuỗi các phạm vi từ vựng lên ngăn xếp và mỗi lần truy cập biến như vậy yêu cầu nhiều bước nhảy gián tiếp lên ngăn xếp để tìm thấy nó. Đắt! C vứt bỏ tất cả những thứ đó. Tôi vẫn nhớ nó
davidbak

12
@davidbak: Hệ thống V86I x86-64 (còn gọi là quy ước gọi trên Linux / OS X) định nghĩa %r10là "con trỏ chuỗi tĩnh", chính xác là những gì bạn đang nói đến. Đối với C, nó chỉ là một thanh ghi cào bị chặn khác, nhưng tôi đoán Pascal sẽ sử dụng nó. (Các hàm lồng nhau của GNU C sử dụng nó để chuyển một con trỏ đến phạm vi bên ngoài khi một hàm như vậy không nội tuyến (ví dụ: nếu bạn tạo một con trỏ hàm cho nó để trình biên dịch tạo ra một tấm bạt lò của mã máy trên ngăn xếp): Chấp nhận thường xuyên sử dụng r10 và r11 )
Peter Cordes

2
@PeterCordes Hấp dẫn! Pascal vẫn được sử dụng rộng rãi khi System V xuất hiện (mặc dù tôi không biết khi nào SysV ABI chính thức được xác định). Câu trả lời liên kết của bạn là rất nhiều thông tin.
davidbak

3
C có các loại do người dùng định nghĩa (struct / union). Phần còn lại của các "tính năng" bị bỏ qua, tôi nghi ngờ, bởi vì chúng không sử dụng hoặc phủ định (trừ khi bạn đang tham gia một cuộc thi mã bị che giấu :-)), vì chúng làm mất đi mục tiêu giữ cho ngôn ngữ vừa đơn giản vừa biểu cảm .
jamesqf

6
@jamesqf: nhưng từ rất sớm C đã không có sự phân công cấu trúc; Tôi đoán bạn phải ghi nhớ hoặc sao chép các thành viên riêng lẻ thay vì viết a = b;để sao chép toàn bộ cấu trúc theo cách bạn có thể trong ISO C89. Vì vậy, vào đầu C, các loại do người dùng định nghĩa chắc chắn là hạng thứ hai và chỉ có thể được chuyển qua tham chiếu dưới dạng hàm args. Sự ác cảm của C đối với các mảng và cả Tại sao C ++ lại hỗ trợ việc gán các mảng thành viên trong các cấu trúc, nhưng nói chung thì không?
Peter Cordes

37

Đầu những năm 1970, C là một luồng không khí trong lành sử dụng các cấu trúc hiện đại hiệu quả đến mức toàn bộ hệ thống UNIX có thể được viết lại từ ngôn ngữ lắp ráp thành C với không gian không đáng kể hoặc hình phạt hiệu suất. Vào thời điểm đó, nhiều người đương thời gọi nó là ngôn ngữ cấp cao.

Các tác giả của C, chủ yếu là Dennis Ritchie, đã lách luật nhiều hơn và trong bài báo của Tạp chí Kỹ thuật Hệ thống Bell cho biết "C không phải là một ngôn ngữ cấp cao." Với một nụ cười gượng gạo và có ý định khiêu khích, Dennis Ritchie sẽ nói đó là một ngôn ngữ cấp thấp. Mục tiêu hàng đầu trong thiết kế của anh đối với C là giữ cho ngôn ngữ gần với máy mà vẫn cung cấp tính di động, đó là tính độc lập của máy.

Để biết thêm thông tin tham khảo bài viết BSTJ gốc:

Cảm ơn bạn Dennis. Bạn có thể nghỉ ngơi trong hòa bình.


3
Về cơ bản, nó được gõ và các hàm bao cú pháp đẹp hơn để lắp ráp PDP nếu bạn hỏi tôi.
einpoklum


2
@einpoklum Tôi có xu hướng đồng ý với điều đó. Tôi đã học C trở lại vào khoảng năm 1980 tại trường đại học, trên PDP-11 / 34a khi nó xảy ra, và nó được một trong những giáo sư mô tả là "ngôn ngữ lắp ráp di động". Có lẽ bởi vì ngoài PDP-11, chúng tôi còn có một số máy CP / M tuyệt vời trong phòng thí nghiệm có sẵn trình biên dịch C trên chúng. vi.wikipedia.org/wiki/Intertec_Superbrain
dgnuff

2
Ngoài ra một câu trả lời tuyệt vời dựa trên bằng chứng lịch sử có thể kiểm chứng (wow! Đã có phiên bản trước của K & R có sẵn ngoài đó!).
Christophe

7
@einpoklum Đây có phải là điều gì đó quá xa vời không? Tôi đã có cơ hội viết mã hệ thống và ứng dụng vào giữa thập niên 80 trong trình biên dịch chương trình (Z80 và M68K), một "trình biên dịch di động" được gọi là M (cú pháp PDP11 với một thanh ghi và lệnh hướng dẫn 16 bit trừu tượng) và C. So với trình biên dịch , C chắc chắn là một ngôn ngữ cấp cao: năng suất của lập trình C là một thứ tự cường độ cao hơn so với trình biên dịch chương trình! Tất nhiên không có chuỗi (SNOBOL), không hỗ trợ tệp dữ liệu riêng (COBOL), không có mã tự tạo (LISP), không có toán nâng cao (APL), không có đối tượng (SIMULA), vì vậy chúng tôi có thể đồng ý rằng nó không cao lắm
Barshe

21

Như tôi đã viết ở nơi khác trên trang này khi ai đó gọi mô hình quản lý bộ nhớ malloc / miễn phí là "lập trình cấp thấp",

Thật buồn cười khi định nghĩa về "cấp thấp" thay đổi theo thời gian. Khi tôi lần đầu tiên học lập trình, bất kỳ ngôn ngữ nào cung cấp mô hình heap được tiêu chuẩn hóa để tạo ra một mô hình phân bổ / miễn phí đơn giản đều có thể được coi là cấp cao thực sự. Trong lập trình cấp thấp, bạn phải tự theo dõi bộ nhớ, (không phải phân bổ, mà là chính các vị trí bộ nhớ!) Hoặc viết phân bổ heap của riêng bạn nếu bạn cảm thấy thực sự ưa thích.

Đối với bối cảnh, đây là vào đầu những năm 90, sau khi C xuất hiện.


Không phải thư viện tiêu chuẩn chỉ là một thứ kể từ khi tiêu chuẩn hóa vào cuối những năm 80 (tốt, dựa trên các API Unix hiện có)? Ngoài ra, lập trình Kernel (vốn là miền vấn đề ban đầu của C) đương nhiên yêu cầu các công cụ cấp thấp như quản lý bộ nhớ thủ công. Tại thời điểm đó, C phải là ngôn ngữ lập trình cấp cao nhất mà một hạt nhân nghiêm trọng đã được viết (tôi nghĩ ngày nay hạt nhân NT cũng sử dụng một lượng C ++ khá lớn).
amon

6
@hyde, tôi đã sử dụng Algol 60, hai phương ngữ FORTRAN khác nhau và một số phương ngữ BASIC khác nhau vào những năm 1970 và không có ngôn ngữ nào trong số đó có con trỏ hoặc phân bổ heap.
Solomon chậm

7
Nói đúng ra, bạn vẫn có thể lập trình mà không cần malloc()bằng cách gọi trực tiếp brk(2)hoặc mmap(2)tự mình quản lý bộ nhớ kết quả. Đó là một PITA khổng lồ không có lợi ích có thể hiểu được (trừ khi bạn tình cờ thực hiện một thứ giống như malloc), nhưng bạn có thể làm điều đó.
Kevin

1
@amon - ngoại trừ các máy dựa trên ngăn xếp đáng chú ý của Burroughs đã được lập trình trong ALGOL từ dưới lên trên ... và sớm hơn nhiều so với Unix. Ồ, và nhân tiện, Multics, vốn là nguồn cảm hứng cho Unix: Viết bằng PL / I. Tương tự như ALGOL, cấp độ cao hơn C.
davidbak

6
Trên thực tế, lý do ngày nay nhiều người trong chúng ta không sử dụng Multics có lẽ liên quan nhiều hơn đến thực tế là nó chỉ chạy trên các máy tính lớn đắt tiền - tức là, chi phí máy tính lớn điển hình trong ngày cộng với chi phí thêm một nửa tủ phần cứng chuyên dụng để thực hiện bộ nhớ ảo với bảo mật. Khi các máy tính mini 32 bit như VAX-11 xuất hiện tất cả mọi người trừ các ngân hàng và chính phủ đã phân rã từ IBM và Bảy chú lùn và đưa quy trình xử lý quy mô lớn của họ sang máy tính "mini".
davidbak

15

Nhiều câu trả lời đã được đề cập đến những bài báo đầu tiên cho biết những điều như Lam C không phải là ngôn ngữ cấp cao.

Tuy nhiên, tôi không thể chống lại việc chồng chất: nhiều, nếu không phải hầu hết hoặc tất cả các HLL tại thời điểm đó - Algol, Algol-60, PL / 1, Pascal - đã cung cấp kiểm tra giới hạn mảng và phát hiện tràn số.

Lần cuối tôi kiểm tra bộ đệm và tràn số nguyên là nguyên nhân gốc của nhiều lỗ hổng bảo mật. ... Đúng, vẫn là trường hợp ...

Tình hình quản lý bộ nhớ động phức tạp hơn, nhưng vẫn vậy, malloc / free kiểu C là một bước lùi lớn về mặt bảo mật.

Vì vậy, nếu định nghĩa về HLL của bạn bao gồm, tự động ngăn chặn nhiều lỗi cấp thấp, thì, trạng thái xin lỗi của an ninh mạng sẽ rất khác, có lẽ tốt hơn, nếu C và UNIX không xảy ra.


7
Vì tôi tình cờ đã tham gia vào việc triển khai Intel MPX và trình biên dịch kiểm tra con trỏ / giới hạn xuất hiện nếu có, tôi có thể giới thiệu cho bạn các bài viết về hiệu suất của chúng: về cơ bản là 5-15%. Phần lớn trong số đó liên quan đến các phân tích trình biên dịch hầu như không thể thực hiện được trong những năm 1970 và 1980 - so với các kiểm tra ngây thơ có thể chậm hơn 50%. Tuy nhiên, tôi nghĩ rằng thật công bằng khi nói rằng C và UNIX đã thiết lập lại các phân tích như vậy sau 20 năm - khi C trở thành ngôn ngữ lập trình phổ biến nhất, thì nhu cầu về an toàn sẽ ít hơn nhiều.
Krazy Glew

9
@jamesqf Hơn nữa, nhiều máy trước C có hỗ trợ phần cứng đặc biệt để kiểm tra giới hạn và tràn số nguyên. Vì C không sử dụng CTNH đó, cuối cùng nó đã bị phản đối và bị loại bỏ.
Krazy Glew

5
@jamesqf Ví dụ: MIPS RISC ISA ban đầu được dựa trên các điểm chuẩn Stanford, ban đầu được viết bằng Pascal, sau đó chỉ chuyển sang C. Vì Pascal đã kiểm tra tràn số nguyên đã ký, do đó MIPS cũng vậy, trong các hướng dẫn như ADD. Circa 2010 Tôi đang làm việc tại MIPS, sếp của tôi muốn xóa các hướng dẫn không sử dụng trong MIPSr6 ​​và các nghiên cứu cho thấy rằng kiểm tra tràn gần như không bao giờ được sử dụng. Nhưng hóa ra Javascript đã kiểm tra như vậy - nhưng không thể sử dụng các hướng dẫn rẻ tiền vì thiếu hỗ trợ HĐH.
Krazy Glew

3
@KrazyGlew - Thật thú vị khi bạn đưa ra điều này vì trong C / C ++, cuộc chiến giữa người dùng và người viết trình biên dịch về "hành vi không xác định" do tràn số nguyên đã ký đang nóng lên, vì các nhà văn trình biên dịch ngày nay đã thực hiện câu thần chú cũ "Làm sai chương trình tệ hơn là không có tội "và biến nó thành 11. Rất nhiều bài đăng trên stackoverflow và những nơi khác phản ánh điều này ...
davidbak

2
Nếu Rust có nội tại SIMD như C, thì đó có thể là ngôn ngữ lắp ráp di động hiện đại gần như lý tưởng. C ngày càng trở nên tồi tệ hơn khi trở thành ngôn ngữ lắp ráp di động do tối ưu hóa dựa trên UB tích cực và không thể phơi bày một cách hợp lý các hoạt động nguyên thủy mới mà CPU hiện đại hỗ trợ (như popcnt, đếm các số 0 đầu / cuối, đảo ngược bit, đảo ngược byte, bão hòa môn Toán). Bắt các trình biên dịch C để tạo ra asm hiệu quả cho các CPU này với sự hỗ trợ CTNH thường đòi hỏi phải có nội tại không di động. Có trình biên dịch mô phỏng popcnt trên các mục tiêu mà không có nó tốt hơn nhận dạng thành ngữ để có được popcnt.
Peter Cordes

8

Xem xét các ngôn ngữ cũ hơn và cao hơn nhiều so với trước C (1972):

Fortran - 1957 (không cao hơn nhiều so với C)

Lisp - 1958

Cobol - 1959

Fortran IV - 1961 (không cao hơn nhiều so với C)

PL / 1 - 1964

APL - 1966

Cộng với một ngôn ngữ cấp trung như RPG (1959), chủ yếu là ngôn ngữ lập trình để thay thế các hệ thống hồ sơ đơn vị dựa trên bảng cắm.

Từ quan điểm này, C dường như là một ngôn ngữ cấp độ rất thấp, chỉ cao hơn một chút so với các trình biên dịch macro được sử dụng trên các máy tính lớn vào thời điểm đó. Trong trường hợp các máy tính lớn của IBM, các macro trình biên dịch chương trình đã được sử dụng để truy cập cơ sở dữ liệu, chẳng hạn như BDAM (phương thức truy cập đĩa cơ bản), do các giao diện cơ sở dữ liệu đã được chuyển sang Cobol (tại thời điểm đó) dẫn đến sự kết hợp của việc lắp ráp và Các chương trình Cobol vẫn được sử dụng ngày nay trên các máy tính lớn của IBM.


2
Nếu bạn muốn liệt kê các ngôn ngữ cũ hơn, cao hơn, đừng quên LISP .
Ded repeatator

@Ded repeatator - Tôi đã thêm nó vào danh sách. Tôi đang tập trung vào những gì được sử dụng trên các máy tính lớn của IBM và tôi không nhớ LISP là phổ biến, nhưng APL cũng là ngôn ngữ thích hợp cho các máy tính lớn của IBM (thông qua bảng điều khiển chia sẻ thời gian) và IBM 1130. Tương tự như LISP, APL là một trong các ngôn ngữ cấp cao độc đáo hơn, ví dụ: xem cần bao nhiêu mã để tạo trò chơi cuộc sống của Conway với phiên bản hiện tại của APL: youtube.com/watch?v=a9xAKttWgP4 .
RCgldr

2
Tôi sẽ không coi RPG hay COBOL là cấp độ đặc biệt cao, ít nhất là không phải trước COBOL-85. Khi bạn làm trầy xước bề mặt của COBOL, bạn sẽ thấy rằng về cơ bản nó là một tập hợp các macro trình biên dịch chương trình rất tiên tiến. Để bắt đầu, nó thiếu cả chức năng, thủ tục và đệ quy, cũng như bất kỳ loại phạm vi nào. Tất cả lưu trữ phải được khai báo ở đầu chương trình dẫn đến việc sử dụng quá nhiều lần hoặc sử dụng lại biến đau đớn.
idrougge

Tôi có một số ký ức tồi tệ khi sử dụng Fortran IV, tôi không nhớ nó được đánh giá là "cấp độ cao" hơn C.
DaveG

@idrougge - Các bộ hướng dẫn của COBOL và RPG, cũng như máy tính lớn bao gồm hỗ trợ đầy đủ cho BCD đóng gói hoặc chưa đóng gói, một yêu cầu đối với phần mềm tài chính ở các quốc gia như Hoa Kỳ. Tôi coi các toán tử gốc có liên quan như "di chuyển tương ứng" là mức cao. RPG khác thường ở chỗ bạn đã chỉ định liên kết giữa các trường đầu vào thô và các trường đầu ra được định dạng và / hoặc bộ tích lũy, nhưng không phải là thứ tự của các hoạt động, tương tự như lập trình bảng bổ trợ mà nó đã thay thế.
RCgldr

6

Câu trả lời cho câu hỏi của bạn phụ thuộc vào ngôn ngữ C mà nó đang hỏi về.

Ngôn ngữ được mô tả trong Hướng dẫn tham khảo C năm 1974 của Dennis Ritchie là ngôn ngữ cấp thấp mang đến sự tiện lợi cho việc lập trình của các ngôn ngữ cấp cao hơn. Các phương ngữ xuất phát từ ngôn ngữ đó cũng có xu hướng là ngôn ngữ lập trình cấp thấp.

Tuy nhiên, khi Tiêu chuẩn C 1989/1990 được xuất bản, nó không mô tả ngôn ngữ cấp thấp đã trở nên phổ biến để lập trình máy thực tế, mà thay vào đó mô tả một ngôn ngữ cấp cao hơn có thể - nhưng không bắt buộc phải - - Thực hiện ở cấp độ thấp hơn.

Như các tác giả của ghi chú C Standard, một trong những điều làm cho ngôn ngữ trở nên hữu ích là nhiều triển khai có thể được coi là trình biên dịch cấp cao. Do C cũng được sử dụng thay thế cho các ngôn ngữ cấp cao khác và vì nhiều ứng dụng không yêu cầu khả năng thực hiện những điều mà ngôn ngữ cấp cao không thể làm được, nên các tác giả của Tiêu chuẩn cho phép thực hiện theo cách tùy tiện nếu các chương trình đã cố gắng sử dụng các cấu trúc cấp thấp. Do đó, ngôn ngữ được mô tả bởi Tiêu chuẩn C chưa bao giờ là ngôn ngữ lập trình cấp thấp.

Để hiểu sự khác biệt này, hãy xem xét cách Ngôn ngữ của Ritchie và C89 sẽ xem đoạn mã:

struct foo { int x,y; float z; } *p;
...
p[3].y+=1;

trên nền tảng trong đó "char" là 8 bit, "int" là 16 bit big endian, "float" là 32 bit và các cấu trúc không có yêu cầu đệm hoặc căn chỉnh đặc biệt nên kích thước của "struct foo" là 8 byte.

Trên Ngôn ngữ của Ritchie, hành vi của câu lệnh cuối cùng sẽ lấy địa chỉ được lưu trong "p", thêm 3 * 8 + 2 [tức là 26] byte vào đó và lấy giá trị 16 bit từ các byte tại địa chỉ đó và tiếp theo , thêm một vào giá trị đó và sau đó ghi lại giá trị 16 bit đó vào cùng hai byte. Hành vi sẽ được định nghĩa là hành động theo các byte thứ 26 và 27 theo sau tại địa chỉ p mà không quan tâm đến loại đối tượng nào được lưu trữ ở đó.

Trong ngôn ngữ được xác định bởi Tiêu chuẩn C, trong trường hợp * p xác định một phần tử của "struct foo []", theo sau là ít nhất ba phần tử hoàn chỉnh hơn của loại đó, câu lệnh cuối cùng sẽ thêm một thành viên vào y phần tử thứ ba sau * p. Hành vi sẽ không được Tiêu chuẩn xác định trong bất kỳ trường hợp nào khác.

Ngôn ngữ của Ritchie là ngôn ngữ lập trình cấp thấp bởi vì, trong khi nó cho phép lập trình viên sử dụng các khái niệm trừu tượng như mảng và cấu trúc khi thuận tiện, nó xác định hành vi theo cách bố trí cơ bản của các đối tượng trong bộ nhớ. Ngược lại, ngôn ngữ được mô tả bởi C89 và các tiêu chuẩn mới hơn xác định mọi thứ theo cách trừu tượng hóa ở cấp độ cao hơn và chỉ xác định hành vi của mã phù hợp với điều đó. Việc triển khai chất lượng phù hợp với lập trình cấp thấp sẽ hành xử hữu ích trong nhiều trường hợp hơn so với tiêu chuẩn bắt buộc, nhưng không có tài liệu "chính thức" nào chỉ rõ việc triển khai phải làm gì để phù hợp với mục đích đó.

Ngôn ngữ C do Dennis Ritchie phát minh là một ngôn ngữ cấp thấp và được công nhận như vậy. Tuy nhiên, ngôn ngữ được phát minh bởi Ủy ban Tiêu chuẩn C, chưa bao giờ là ngôn ngữ cấp thấp trong trường hợp không có các đảm bảo được cung cấp thực hiện vượt xa các nhiệm vụ của Tiêu chuẩ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.