Tại sao mảng không thể được chuyển qua làm đối số hàm trong C?


12

Theo nhận xét này , tôi đã cố gắng google tại sao, nhưng google-fu của tôi không thành công.

Nhận xét từ liên kết:

[...] Nhưng điều quan trọng là mảng và con trỏ là những thứ khác nhau trong C.

Giả sử bạn không sử dụng bất kỳ tiện ích mở rộng trình biên dịch nào, bạn thường không thể tự truyền một mảng cho một hàm, nhưng bạn có thể truyền một con trỏ và lập chỉ mục một con trỏ như thể đó là một mảng.

Bạn đang phàn nàn một cách hiệu quả rằng con trỏ không có chiều dài kèm theo. Bạn nên phàn nàn rằng các mảng không thể được chuyển qua dưới dạng đối số hàm hoặc các mảng suy giảm thành con trỏ hoàn toàn.


Tôi không chắc đó là câu trả lời, nhưng một phần của kiểu mảng là kích thước của nó, vì vậy tôi tin rằng bạn sẽ phải xác định hàm cho mọi kích thước bạn muốn chấp nhận.
clcto

Bạn có nghĩa là con trỏ chức năng ? Hãy làm rõ câu hỏi.
dùng949300

2
@ user949300 Không, từ ngữ cảnh của bình luận, nó khá rõ ràng; bạn không thể truyền một mảng cho một hàm vì nó trở thành một con trỏ và anh ta muốn biết tại sao lại như vậy.
Doval

@DocBrown rlemon đề xuất một chỉnh sửa cho việc này.
Florian Margaine

Câu trả lời:


18

Dự đoán đầu tiên của tôi về lý do đơn giản là vì lý do hiệu năng và tiết kiệm bộ nhớ, và để dễ thực hiện trình biên dịch (đặc biệt là đối với loại máy tính tại thời điểm C được phát minh). Truyền các mảng lớn "theo giá trị" dường như có tác động rất lớn đến ngăn xếp, nó cần một thao tác sao chép toàn bộ mảng cho mỗi lệnh gọi hàm và có lẽ trình biên dịch phải thông minh hơn để xuất mã lắp ráp chính xác (mặc dù điểm cuối còn gây tranh cãi) . Cũng sẽ khó khăn hơn khi xử lý các mảng được phân bổ động giống như các mảng được phân bổ tĩnh (theo quan điểm của cú pháp của ngôn ngữ).

EDIT: sau khi đọc một số bộ phận từ liên kết này , tôi nghĩ rằng lý do thực sự (và lý do tại sao các mảng trong cấu trúc được coi là loại giá trị, trong khi mảng duy nhất là không) là khả năng tương thích ngược với C của người tiền nhiệm B . Đây là trích dẫn từ Dennis Ritchie:

... Quy tắc, tồn tại trong C ngày nay, là các giá trị của kiểu mảng được chuyển đổi, khi chúng xuất hiện trong biểu thức, thành con trỏ đến đầu tiên của các đối tượng tạo thành mảng.

Phát minh này cho phép hầu hết mã B hiện tại tiếp tục hoạt động, bất chấp sự thay đổi cơ bản trong ngữ nghĩa của ngôn ngữ. [..]


5
A struct Foo { int array[N]; } có thể được thông qua bởi giá trị. Và điều cuối cùng về việc xử lý phân bổ động và tĩnh giống nhau có vẻ tẻ nhạt (một mảng theo nghĩa chặt chẽ nhất luôn bao gồm một kích thước, các khái niệm thống nhất cho những thứ như lập chỉ mục mảng là các con trỏ kết hợp với phân rã mảng-con trỏ), bạn có thể giải thích không?

@delnan: Tôi nghĩ rằng các nguyên tắc chung được nêu ở đây là âm thanh. Rõ ràng, nếu bạn bọc mảng của bạn trong một cấu trúc, bạn đang chỉ định ý định của mình. Trong trường hợp chung, bạn hầu như luôn luôn vượt qua bằng cách tham khảo.
Robert Harvey

Tôi cũng tìm thấy các bình luận được tham chiếu trong OP pedantic không cần thiết. Rõ ràng bạn đang truyền một con trỏ chứ không phải là một mảng theo giá trị. Tuy nhiên, điều cũng đúng như vậy là bạn thực sự chuyển một mảng bằng cách tham chiếu. Nếu sự phản đối là không có độ dài kèm theo, thì cũng đủ để vượt qua điều đó.
Robert Harvey

@RobertHarvey Điều đó vẫn không đối xứng trong hệ thống loại: Mọi thứ đều được truyền theo giá trị, ngoại trừ các kiểu mảng (mặc dù các mảng là một phần của kiểu cấu trúc được truyền theo giá trị) và thậm chí nó còn sử dụng cùng một ký hiệu chính xác (cả tại trang web cuộc gọi và trong chữ ký hàm).

@delnan: Tại sao điều đó có liên quan, ngoài việc bạn phải nhớ nó?
Robert Harvey

9

Một máy tính mini PDP chỉ có 8 kB bộ nhớ không thể phân bổ một ngăn xếp rất lớn. Vì vậy, trên một máy như vậy, người ta phải cẩn thận trong thiết kế ngôn ngữ (hoặc tiến hóa) để có thể giảm thiểu những gì cần phải thực hiện trên ngăn xếp để sử dụng cuộc gọi chương trình con phổ biến dự kiến. C vẫn được sử dụng ngày nay để lập trình các hệ thống nhúng cực kỳ hạn chế bộ nhớ (một vài kB), vì vậy sự đánh đổi thường là một hệ thống tốt.

Trên một kiến ​​trúc bộ xử lý có rất ít thanh ghi, việc truyền bất kỳ mảng nào bằng con trỏ thay vì theo giá trị thường cho phép một thanh ghi được sử dụng như một tối ưu hóa cuộc gọi chương trình con.


2
Tôi có một số bảng có 256 byte RAM cho dữ liệu và 2K EEPROM cho mã. Bạn không muốn tạo một bản sao của một mảng ở đó.
Jerry Jeremiah
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.