2009-08-11 3 views
15

Tôi muốn biết, tại sao nó quá khó để làm cho một chương trình chạy trong nhiều hệ điều hành, như Windows và Linux, mà không bao gồm mã keo. Tất cả đều chia sẻ cùng một kiến ​​trúc (x86), vì vậy tôi nghĩ nó nên đơn giản. Hơn nữa, C được chuẩn hóa, vậy tại sao các triển khai khác nhau trong các hệ điều hành này? Tại sao khó tuân theo tiêu chuẩn và triển khai một thư viện chung cho tất cả các hệ điều hành?Tại sao khó viết các chương trình C di động?

Tôi đã lập trình trong C gần hai năm và hiện tại tôi sử dụng glib cho tính di động.

Tôi không tìm kiếm giải pháp cho vấn đề này, tôi đã sử dụng glib cho mục đích này. Nhưng tôi muốn biết lý do tại sao nó là cần thiết, tại sao nó dificult để làm cho một thư viện C mà không có sự khác biệt.

[ADD]

Ví dụ, khi tôi viết một chương trình trong C/Glib, tôi sử dụng các gchar/gint và vân vân các loại thực sự là loại nguyên thủy C, trong wikipedia về lém lỉnh, nó nói rằng:

"Tính năng

trên một trình độ sơ cấp GLib cung cấp định nghĩa kiểu thay thế các loại nguyên thủy C char, int, float, và vân vân nhằm nâng cao tính di động"

Tại sao C loại nguyên thủy không di động và toàn bộ ngôn ngữ?

Cảm ơn tất cả các câu trả lời.

+0

Ghi đè của C loại nguyên thủy thực sự là để phục vụ cho các CPU khác nhau. Linux chạy trên rất nhiều CPU khác nhau và thậm chí Windows hỗ trợ các chế độ hoạt động khác nhau của x86 (32 và 64 bit). C bây giờ có int32_t, uint16_t vv để cải thiện mọi thứ một chút. – Dipstick

+0

Cảm ơn tất cả các câu trả lời, tôi thực sự sẽ không chọn câu trả lời để đóng chủ đề này, bởi vì tôi nghĩ rằng mỗi câu trả lời hoàn thành lẫn nhau. nhưng, tôi phải chọn câu trả lời tốt nhất, vì vậy tôi chọn de nhiều hơn bình chọn, cảm ơn rất nhiều cho bạn thời gian, D – drigoSkalWalker

+0

Tôi đã quay trở lại thay đổi tiêu đề của bạn. Ngay cả khi bạn đã hoàn thành chủ đề, những người khác vẫn có thể tìm thấy cách sử dụng cho nó và "đóng" có ý nghĩa cụ thể ở đây. – dmckee

Trả lời

25

Làm cho chương trình C cơ bản của bạn tính toán một chút và in kết quả hoạt động rất dễ dàng.

Vấn đề là bất kỳ chương trình C nào thực hiện bất cứ điều gì đáng kể sẽ phụ thuộc vào rất nhiều dịch vụ từ hệ điều hành và những điều khác nhau theo nhiều cách. File I/O có xu hướng tương tự, nhưng khi nói đến đồ họa, chúng khác nhau rất nhiều. Và đó là mấu chốt của vấn đề.

+4

Ngay cả tệp I/O, thư viện chuẩn C cung cấp chức năng, là một mớ hỗn độn. Việc cố gắng làm tập tin I/O và quyền _securely_ là một nỗi đau ở mức tốt nhất, và không thể trong nhiều tình huống. Hãy xem xét rằng tất cả các hàm C/I của tệp C yêu cầu tên tệp để nhận dạng. Điều này có thể gây ra các điều kiện chủng tộc (vô hại) khi bạn kiểm tra sự tồn tại của tệp rồi mở một trong cùng tên I/O. Xem https://www.securecoding.cert.org/confluence/display/seccode/09.+Input+Output+%28FIO%29 để biết thêm :) –

+0

có; kiến trúc bộ vi xử lý cơ bản được trừu tượng hóa tốt bằng ngôn ngữ C (ngoài một số kiểu phụ thuộc vào độ rộng của bộ đếm). Đó là hệ điều hành mà bạn thực sự cần, và được hỗ trợ kém bởi các thư viện chuẩn. Trong thực tế: bạn thậm chí có thể xem xét Glib hoặc Qt như mã keo, chỉ có bạn không cần phải viết nó cho mình. – Adriaan

15

Không khó nếu bạn tuân theo tiêu chuẩn cốt lõi (ví dụ trong K & R thường sẽ chạy với hiệu chỉnh tối thiểu). Nhưng tiêu chuẩn cốt lõi không hỗ trợ nhiều thứ mà mọi người muốn làm. những điều nhỏ nhặt như:

  • rễ xung quanh trong hệ thống tập tin
  • phức tạp hơn IO hơn văn bản trực tiếp đồng bằng
  • hỏi hệ điều hành để truy cập vào đồng hồ và máy in và mạng
  • nói chuyện với các quá trình khác

Liên quan đến tính di động của các loại nguyên thủy: tiêu chuẩn xác định giới hạn kích thước tối thiểu cho các loại này, nhưng không chỉ định các kích thước thực tế. Hầu hết các nền tảng đều hỗ trợ các kích thước lớn hơn mức tối thiểu, nhưng không phải tất cả các nền tảng đều có kích thước lớn hơn cùng một kích thước lớn hơn. Vì vậy, glib và các dự án đa nền tảng khác xác định loại riêng của chúng để chúng chỉ cần một bộ thiết bị chuyển mạch #ifdef để có được kích thước phù hợp.

0

Tôi nghĩ đó là bởi vì mọi trình biên dịch đều có sự căng thẳng giữa tiêu chuẩn và di động trên một mặt và sử dụng các tính năng tối ưu, độc quyền của hệ điều hành trên một mặt khác.

Tôi nghĩ mã ANSI C khá di động, miễn là bạn ghi vào tiêu chuẩn. Mã của bạn được di chuyển đến mức độ mà GNU và Microsoft đều gắn bó với tiêu chuẩn.

7

Bất cứ điều gì mà chương trình C của bạn tương tác sẽ là phụ thuộc. Nếu những phụ thuộc đó là chính xác giống nhau trên mọi triển khai C trên tất cả các hệ thống, thì bạn may mắn, chương trình của bạn là di động.

Các hoạt động I/O tệp cơ bản theo cách này.

Nhưng nếu thậm chí có một sự khác biệt trong cách mã của bạn được triển khai trên một hệ thống, nó không thể di chuyển sang hệ thống đó nữa.

Vì vậy, nếu mã của bạn không chạm vào bất cứ thứ gì, nó sẽ di động.

Tôi nghĩ ý tưởng chính ở đây là để tối đa hóa khả năng di động, để bạn có thể giảm thiểu những gì bạn phải thay đổi để chuyển sang một hệ thống mới.

3

Mã di động, nhưng đó không phải là vấn đề.

Vấn đề là hầu hết các ứng dụng lớn hơn đều sử dụng thư viện là một phần của hệ điều hành. Vì vậy, ví dụ nếu bạn viết một ứng dụng mạng, nó có thể sử dụng thư viện UPNP tích hợp cho các cửa sổ, và thư viện Bonjour trên OS X, và một số dịch vụ zero-conf khác trên các hương vị khác unix.

Ví dụ khác có thể là ứng dụng notepad đơn giản. Nó có thể sử dụng các hộp thoại lưu tệp gốc cho hệ điều hành mà nó đang chạy. Một phiên bản khác sẽ cần phải được biên dịch cho mỗi hệ điều hành để liên kết với thư viện lưu trữ đối thoại cho hệ điều hành đó.

Tôi hy vọng những ví dụ này rõ ràng đủ :)

19

Tại sao C loại nguyên thủy không phải là di động và toàn bộ ngôn ngữ?

Đồng thời C đã được tạo ra, nó được coi là quan trọng nhất mà int sử dụng kích thước tự nhiên từ (hoặc kích thước nữa vòng trái đất) của máy mục tiêu (mà trong những ngày đó có thể là 18 hoặc 36 bit trên một PDP- 10!), Và ít quan trọng là số lượng bit trong một int có thể dễ dàng dự đoán được, hãy để một mình trên tất cả phần cứng. Hiệu quả là mối quan tâm tối thượng, và điều đặc biệt quan trọng là một chương trình không có quá nhiều chỉ dẫn, để nó có thể được đóng gói vào những kỷ niệm nhỏ trong ngày. Chẳng hạn, chẳng ai muốn mô phỏng số học 32 bit trên máy 16 bit — có thể tăng gấp ba số lượng lệnh cần thiết để làm phép tính số học, làm cho nó không thể phù hợp với các chương trình lớn hơn vào bộ nhớ.

Tại sao khó triển khai thư viện chung?

Không hề khó chút nào. Vấn đề không phải là không có thư viện phổ quát; vấn đề là mọi người không thể đồng ý về những gì tạo thành một thư viện phổ thông. (Xem: GTK, KDE, QT, AT & T U/WIN + AST, v.v.) Nhưng việc triển khai thư viện tốtthực sự là.Về lý do tại sao nó khó khăn: thiết kế thư viện chỉ là một vấn đề khó khăn, và những người hợp lý có thể và không đồng ý về những gì tạo thành một thiết kế tốt. Vì vậy, nhiều thiết kế sinh sôi nảy nở, và tính di động của hội đồng quản trị.

Tình hình trở nên trầm trọng hơn bởi thư viện chuẩn rất mỏng đi kèm C. Nhưng chúng ta đừng quên rằng thư viện được thiết kế vào những ngày mà một lập trình viên may mắn nhận được 64KB cho mã và 64KB khác cho dữ liệu. Bởi thời gian C++ đến, họ có thể đủ khả năng để tiêu chuẩn hóa trên một con heo cồng kềnh to lớn như Thư viện mẫu chuẩn. Nhưng khi thư viện C được thiết kế, mọi thứ là nhỏ. Bây giờ, khi thư viện C chuẩn không đủ cho các ứng dụng tham vọng ngày nay, thì đã quá muộn để tất cả các lập trình viên C đồng ý với một tiêu chuẩn duy nhất.


Poke một giáo sư, có được một bài giảng ...

+4

Tôi nghĩ rằng điều này có lẽ là một chút revisionist. Vào thời điểm C được tạo ra, nó đã được dự định sẽ được sử dụng trên một nền tảng cụ thể (PDP-11), và chỉ cần phân tán cho người khác một mình. Mỗi người triển khai cá nhân đã đưa ra quyết định riêng của họ về kích thước để tạo ra 'int' khác nhau. Không có tiêu chuẩn vào thời điểm đó, và khi một tiêu chuẩn đã thành hiện thực, tất cả những gì nó thực sự làm là mã hóa pactice hiện có trong cộng đồng trình biên dịch. Phần lớn những gì chúng ta biết về một C ngày nay không thực sự được thiết kế, nhưng loại phát triển hữu cơ. –

1

Đối với java/ruby ​​/ ... ai đó chuyển máy ảo và mã của bạn chỉ chạy. Điều này làm cho nó dễ dàng miễn là bạn ok với các dịch vụ được cung cấp bởi máy ảo. Trong C bạn phải tự làm tất cả công việc vì bạn có thể tương tác trực tiếp với phần cứng và hệ điều hành. Điều này làm tăng thêm sự phụ thuộc nhưng mang lại cho bạn sức mạnh và sự linh hoạt tuyệt vời. Đây là những gì làm cho C tuyệt vời nhưng nó có thể là một nỗi đau nếu bạn chuyển đổi hệ điều hành hoặc phần cứng.

0

C cung cấp nhiều quyền lực hơn so với các ngôn ngữ cấp cao khác.

Bộ xử lý khác nhau (dựa trên CISC và RISC), 32 và 64bits đặt các luồng dữ liệu bit theo thứ tự khác nhau. Có một số API hỗ trợ để thực hiện chuyển đổi, nhưng không hoàn toàn đáng tin cậy cho tất cả các trường hợp.

Windows và Unix có cờ tùy chỉnh cần được sử dụng để xây dựng.

1

Rõ ràng, một số phần mềm yêu cầu tính năng cụ thể hệ điều hành, nhưng nó khá thú vị để suy nghĩ những gì có thể được tạo ra trong C mà không sử dụng những thứ như:

  • AC hoặc C++ biên dịch (mặc dù không phải tất cả các thư viện chuẩn)
  • một lắp ráp cho bất kỳ ngôn ngữ lắp ráp
  • một mối liên kết cho trên
  • một thông dịch cho một ngôn ngữ kịch bản
  • công cụ xử lý
  • chữ như sed, grep, vv
  • Một biên tập đơn giản (ai nhớ ed?)

Trong thực tế, tất cả các công cụ phát triển cơ bản có thể được xây dựng (và lịch sử được xây dựng) trong C mà không sử dụng các tính năng hệ điều hành cụ thể.

1

Tại sao C loại nguyên thủy không di động và toàn bộ ngôn ngữ?

Các loại nguyên thủy là xách tay ở chỗ chúng được bảo đảm để hỗ trợ một phạm vi tối thiểu là giá trị (ví dụ, các kiểu int phải ít nhất giá trị hỗ trợ trong phạm vi -32.767-32.767). Chúng không được đảm bảo có cùng giới hạn kích thước hoặc căn chỉnh vì các kiến ​​trúc khác nhau có các yêu cầu khác nhau.

Chuẩn C cố gắng đạt được sự cân bằng hợp lý giữa tính di động, hiệu suất và dễ thực hiện, có nghĩa là có sự thỏa hiệp trong cả ba lĩnh vực.Có thể viết các chương trình C hữu ích và dễ dàng di chuyển, nhưng điều đó có nghĩa là giới hạn bản thân với giao diện điều khiển dòng lệnh, tệp I/O đơn giản và không đưa ra giả định về kích thước hoặc căn chỉnh từ.

Hãy nhớ rằng C là sản phẩm của những năm 70, khi môi trường điện toán chiếm ưu thế bao gồm các hệ thống chia sẻ thời gian lớn được truy cập thông qua các thiết bị đầu cuối dựa trên ký tự câm; thời gian xử lý và bộ nhớ rất tốn kém, và hiếm khi một trung tâm dữ liệu hỗ trợ nhiều hơn một hoặc hai nền tảng khác nhau tại một thời điểm, do đó hiệu suất là mối quan tâm lớn hơn tính di động byte-byte. Bốn mươi năm sau đó không còn là trường hợp, nhưng cũng có bốn mươi năm mã di sản để hỗ trợ, do đó định nghĩa ngôn ngữ không thể thay đổi quá triệt để.