Tại sao các hàm C không thể được đặt tên?


136

Tôi đã có một cuộc phỏng vấn gần đây và một câu hỏi được đặt ra là việc sử dụng extern "C"mã C ++ là gì. Tôi đã trả lời rằng đó là sử dụng các hàm C trong mã C ++ vì C không sử dụng xáo trộn tên. Tôi đã được hỏi tại sao C không sử dụng xáo trộn tên và thành thật mà nói tôi không thể trả lời.

Tôi hiểu rằng khi trình biên dịch C ++ biên dịch các hàm, nó đặt một tên đặc biệt cho hàm chủ yếu vì chúng ta có thể có các hàm quá tải cùng tên trong C ++ phải được giải quyết tại thời điểm biên dịch. Trong C, tên của hàm sẽ giữ nguyên hoặc có thể có dấu _ trước nó.

Truy vấn của tôi là: có gì sai khi cho phép trình biên dịch C ++ thu thập các hàm C? Tôi đã giả định rằng nó không quan trọng tên trình biên dịch đặt cho họ. Chúng ta gọi các hàm theo cùng một cách trong C và C ++.


75
C không cần phải xáo trộn tên, vì nó không có chức năng quá tải.
EOF

9
Làm thế nào để bạn liên kết các thư viện C với mã C ++ nếu trình biên dịch C ++ thu thập tên hàm?
Mat

6
"Tôi đã trả lời rằng đó là sử dụng các hàm C trong mã C ++ vì C không sử dụng xáo trộn tên." - Tôi nghĩ đó là cách khác. Extern "C" làm cho các hàm C ++ có thể sử dụng được trong trình biên dịch C. nguồn
rozina

3
@ Engineering999: Và nếu bạn biên dịch tập hợp con của C cũng là C ++ với trình biên dịch C ++, tên hàm thực sự sẽ bị xáo trộn. Nhưng nếu bạn muốn có thể liên kết các tệp nhị phân được tạo bằng các trình biên dịch khác nhau, bạn không muốn xáo trộn tên.
EOF

13
C tên mangle. Thông thường, tên xéo là tên của hàm đứng trước dấu gạch dưới. Đôi khi, đó là tên của hàm theo sau là dấu gạch dưới. extern "C"nói để mang tên giống như cách mà trình biên dịch "C" sẽ làm.
Pete Becker

Câu trả lời:


187

Nó đã được trả lời ở trên, nhưng tôi sẽ cố gắng đưa mọi thứ vào bối cảnh.

Đầu tiên, C đến trước. Như vậy, những gì C làm là, loại, "mặc định". Nó không mang tên vì nó chỉ không. Tên hàm là tên hàm. Một toàn cầu là một toàn cầu, và như vậy.

Rồi C ++ xuất hiện. C ++ muốn có thể sử dụng cùng một trình liên kết như C và để có thể liên kết với mã được viết bằng C. Nhưng C ++ không thể rời khỏi C "xáo trộn" (hoặc thiếu ở đó). Kiểm tra ví dụ sau:

int function(int a);
int function();

Trong C ++, đây là các chức năng riêng biệt, với các cơ quan riêng biệt. Nếu không ai trong số chúng được đọc sai, cả hai sẽ được gọi là "hàm" (hoặc "_factor") và trình liên kết sẽ phàn nàn về việc xác định lại biểu tượng. Giải pháp C ++ là đưa các kiểu đối số vào tên hàm. Vì vậy, một cái được gọi _function_intvà cái kia được gọi _function_void(không phải sơ đồ xáo trộn thực tế) và tránh va chạm.

Bây giờ chúng tôi còn một vấn đề. Nếuint function(int a) được định nghĩa trong mô-đun C và chúng tôi chỉ lấy tiêu đề của nó (nghĩa là khai báo) trong mã C ++ và sử dụng nó, trình biên dịch sẽ tạo một lệnh cho trình liên kết để nhập _function_int. Khi hàm được định nghĩa, trong mô-đun C, nó không được gọi như vậy. Nó được gọi là _function. Điều này sẽ gây ra lỗi liên kết.

Để tránh lỗi đó, trong quá trình khai báo hàm, chúng tôi nói với trình biên dịch, đó là một hàm được thiết kế để được liên kết với, hoặc được biên dịch bởi, trình biên dịch C:

extern "C" int function(int a);

Trình biên dịch C ++ bây giờ biết nhập _functionhơn là _function_int, và tất cả đều tốt.


1
@ShacharShamesh: Tôi đã hỏi điều này ở nơi khác, nhưng, còn liên kết trong các thư viện được biên dịch C ++ thì sao? Khi trình biên dịch bước qua và biên dịch mã của tôi gọi một trong các hàm trong thư viện được biên dịch C ++, làm thế nào để biết tên nào sẽ mang tên hoặc cung cấp cho hàm khi chỉ nhìn thấy lệnh gọi hoặc hàm của nó? Làm thế nào để biết rằng nơi nó được định nghĩa, nó được đặt tên theo thứ gì khác? Vì vậy, phải có một phương pháp xáo trộn tên tiêu chuẩn trong C ++?
Kỹ

2
Mỗi trình biên dịch làm điều đó theo cách đặc biệt của riêng mình. Nếu bạn đang biên dịch mọi thứ với cùng một trình biên dịch thì không vấn đề gì. Nhưng nếu bạn cố gắng sử dụng, giả sử, một thư viện được biên dịch bằng trình biên dịch của Borland, từ một chương trình mà bạn đang xây dựng với trình biên dịch của Microsoft, thì ... chúc may mắn; bạn sẽ cần nó :)
Đánh dấu VY

6
@ Engineering999 Bạn có bao giờ tự hỏi tại sao không có thư viện C ++ di động nào không, nhưng họ chỉ định chính xác phiên bản (và cờ) nào của trình biên dịch (và thư viện chuẩn) mà bạn phải sử dụng hoặc chỉ xuất API C? Có bạn đi. C ++ là ngôn ngữ di động ít nhất từng được phát minh, trong khi C thì hoàn toàn ngược lại. Có những nỗ lực trong vấn đề đó, nhưng bây giờ nếu bạn muốn thứ gì đó thực sự di động, bạn sẽ gắn bó với C.
Voo

1
@Voo Vâng, về lý thuyết, bạn sẽ có thể viết mã di động chỉ bằng cách tuân thủ tiêu chuẩn -std=c++11, ví dụ , và tránh sử dụng bất cứ thứ gì ngoài tiêu chuẩn. Điều đó giống như việc khai báo một phiên bản Java (mặc dù các phiên bản Java mới hơn tương thích ngược). Đó không phải là lỗi tiêu chuẩn mà mọi người sử dụng các phần mở rộng cụ thể của trình biên dịch và mã phụ thuộc nền tảng. Mặt khác, bạn không thể đổ lỗi cho họ, vì có rất nhiều thứ (đặc biệt là IO, như ổ cắm) bị thiếu trong tiêu chuẩn. Ủy ban dường như đang dần bắt kịp điều đó. Sửa tôi nếu tôi bỏ lỡ điều gì đó.
mucaho

14
@mucaho: bạn đang nói về tính di động / khả năng tương thích nguồn. tức là API. Voo đang nói về khả năng tương thích nhị phân , mà không cần biên dịch lại. Điều này đòi hỏi khả năng tương thích ABI . Trình biên dịch C ++ thường xuyên thay đổi ABI giữa các phiên bản. (vd để làm điều đó.).
Peter Cordes

45

Nói chung không phải là họ "không thể", nói chung họ không .

Nếu bạn muốn gọi một hàm trong thư viện C được gọi foo(int x, const char *y), sẽ không tốt khi để trình biên dịch C ++ của bạn đưa nó vàofoo_I_cCP() (hoặc bất cứ điều gì, chỉ cần tạo ra một sơ đồ xâu chuỗi tại chỗ) chỉ vì nó có thể.

Tên đó sẽ không giải quyết, hàm nằm trong C và tên của nó không phụ thuộc vào danh sách các loại đối số của nó. Vì vậy, trình biên dịch C ++ phải biết điều này và đánh dấu chức năng đó là C để tránh thực hiện việc xáo trộn.

Hãy nhớ rằng hàm C đã nói có thể nằm trong thư viện có mã nguồn mà bạn không có, tất cả những gì bạn có là tệp nhị phân được biên dịch sẵn và tiêu đề. Vì vậy, trình biên dịch C ++ của bạn không thể làm "đó là chuyện riêng", rốt cuộc nó không thể thay đổi những gì trong thư viện.


Đây là phần tôi đang thiếu. Tại sao trình biên dịch C ++ sẽ xáo trộn một tên hàm khi nó nhìn thấy khai báo của nó chỉ hoặc thấy nó được gọi. Nó không chỉ mang tên hàm khi nó thấy việc thực hiện của chúng? Điều này sẽ có ý nghĩa hơn với tôi
Kỹ

13
@ Kỹ sư999: Làm thế nào bạn có thể có một tên cho định nghĩa và một tên khác cho khai báo? "Có một chức năng gọi là Brian mà bạn có thể gọi." "Được rồi tôi sẽ gọi cho Brian." "Xin lỗi, không có chức năng gọi là Brian." Hóa ra nó được gọi là Graham.
Các cuộc đua nhẹ nhàng trong quỹ đạo

Điều gì về liên kết trong các thư viện biên dịch C ++? Khi trình biên dịch bước qua và biên dịch mã của chúng ta gọi một trong các hàm trong thư viện được biên dịch C ++, làm thế nào để biết tên nào sẽ mang tên hoặc cung cấp cho hàm khi chỉ nhìn thấy lệnh gọi hoặc hàm của nó?
Kỹ

1
@ Kỹ sư999 Cả hai phải đồng ý về việc xáo trộn giống nhau. Vì vậy, họ thấy tệp tiêu đề (hãy nhớ rằng, có rất ít siêu dữ liệu trong các tệp DLL gốc - tiêu đề là siêu dữ liệu đó) và đi "Ah, phải, Brian thực sự phải là Graham". Nếu điều này không hoạt động (ví dụ với hai sơ đồ xáo trộn không tương thích), bạn sẽ không nhận được một liên kết chính xác và ứng dụng của bạn sẽ thất bại. C ++ có rất nhiều điểm không tương thích như thế này. Trong thực tế, sau đó bạn phải sử dụng rõ ràng tên xéo và tắt tính năng xáo trộn về phía bạn (ví dụ: bạn nói mã của mình để thực thi Graham, không phải Brian). Trong thực tế thực tế ... extern "C":)
Luaan

1
@ Engineering999 Tôi có thể sai, nhưng bạn có thể có kinh nghiệm với các ngôn ngữ như Visual Basic, C # hoặc Java (hoặc thậm chí là Pascal / Delphi ở một mức độ nào đó) không? Những người làm cho interop dường như vô cùng đơn giản. Trong C và đặc biệt là C ++, đó là bất cứ điều gì nhưng. Có rất nhiều quy ước gọi bạn cần tôn trọng, bạn cần biết ai chịu trách nhiệm về bộ nhớ nào và bạn phải có các tệp tiêu đề cho bạn biết các khai báo hàm, vì bản thân DLL không chứa đủ thông tin - đặc biệt là trong trường hợp thuần C. Nếu bạn không có tệp tiêu đề, bạn thường cần dịch ngược DLL để sử dụng.
Luaan

32

Có gì sai khi cho phép trình biên dịch C ++ mang hàm C?

Chúng sẽ không còn là chức năng C nữa.

Một chức năng không chỉ là một chữ ký và một định nghĩa; làm thế nào một chức năng hoạt động được xác định chủ yếu bởi các yếu tố như quy ước gọi. "Giao diện nhị phân ứng dụng" được chỉ định để sử dụng trên nền tảng của bạn mô tả cách các hệ thống nói chuyện với nhau. Hệ thống C ++ ABI được sử dụng bởi hệ thống của bạn chỉ định sơ đồ xáo trộn tên, để các chương trình trên hệ thống đó biết cách gọi các hàm trong thư viện, v.v. (Đọc C ++ Itanium ABI để biết ví dụ tuyệt vời. Bạn sẽ nhanh chóng thấy lý do cần thiết.)

Điều tương tự áp dụng cho C ABI trên hệ thống của bạn. Một số C ABI thực sự có sơ đồ xáo trộn tên (ví dụ Visual Studio), vì vậy đây không phải là "tắt xáo trộn tên" và nhiều hơn về việc chuyển từ C ++ ABI sang C ABI, cho một số chức năng nhất định. Chúng tôi đánh dấu các hàm C là các hàm C, trong đó C ABI (chứ không phải C ++ ABI) thích hợp. Tuyên bố phải phù hợp với định nghĩa (có thể trong cùng một dự án hoặc trong một thư viện của bên thứ ba), nếu không thì khai báo là vô nghĩa. Không có điều đó, hệ thống của bạn sẽ không biết cách xác định / gọi các chức năng đó.

Về lý do tại sao các nền tảng không định nghĩa ABI của C và C ++ giống nhau và thoát khỏi "vấn đề" này, đó là một phần lịch sử - ABI C ban đầu không đủ cho C ++, có quá trình đặt tên, lớp và toán tử quá tải, tất cả trong đó cần phải được biểu thị bằng tên biểu tượng theo cách thân thiện với máy tính - nhưng người ta cũng có thể lập luận rằng việc tạo các chương trình C bây giờ tuân theo C ++ là không công bằng đối với cộng đồng C, điều này sẽ phải đưa ra một vấn đề phức tạp hơn ABI chỉ vì lợi ích của một số người khác muốn có khả năng tương tác.


2
+int(PI/3), Nhưng với một hạt muối: Tôi sẽ rất thận trọng để nói về "C ++ ABI" ... AFAIK, có nỗ lực ở định C ++ Abis, nhưng không thực de facto / de jure tiêu chuẩn - như isocpp.org/files /papers/n4028.pdf bang (và tôi hết lòng đồng ý), dấu ngoặc, nó là sâu sắc mỉa mai rằng C ++ thực sự đã luôn ủng hộ một cách để xuất bản một API với một ổn định nhị phân ABI-by phải dùng đến các tập hợp con của C C ++ qua extern “C Mùi. . C++ Itanium ABIchỉ là vậy - một số C ++ ABI cho Itanium ... như đã thảo luận trên stackoverflow.com/questions/7492180/c-abi-issues-list

3
@vaxquis: Vâng, không phải "ABI của C ++", mà là "ABI C ++" giống như cách tôi có "chìa khóa nhà" không hoạt động trên mọi nhà. Đoán nó có thể rõ ràng hơn, mặc dù tôi đã cố gắng làm cho nó rõ ràng nhất có thể bằng cách bắt đầu với cụm từ "C ++ ABI được sử dụng bởi hệ thống của bạn " . Tôi đã bỏ công cụ làm rõ trong các lần phát biểu sau để lấy ngắn gọn, nhưng tôi sẽ chấp nhận một chỉnh sửa làm giảm sự nhầm lẫn ở đây!
Các cuộc đua nhẹ nhàng trong quỹ đạo

1
AIUI C abi's có xu hướng là một tài sản của một nền tảng trong khi C ++ ABIs có xu hướng là một thuộc tính của một trình biên dịch riêng lẻ và thường là một thuộc tính của một phiên bản riêng của trình biên dịch. Vì vậy, nếu bạn muốn liên kết giữa các mô-đun được xây dựng với các công cụ nhà cung cấp khác nhau, bạn phải sử dụng C abi cho giao diện.
cắm vào

Câu lệnh "các hàm được xáo trộn tên sẽ không còn là các hàm C nữa" được phóng đại - hoàn toàn có thể gọi các hàm xáo trộn tên từ vanilla C đơn giản nếu biết tên xáo trộn. Việc thay đổi tên không làm cho nó ít tuân thủ C ABI hơn, tức là không làm cho nó trở thành một hàm C ít hơn. Một cách khác, vòng có ý nghĩa hơn - mã C ++ không thể gọi hàm C mà không khai báo là "C" bởi vì nó sẽ thực hiện việc xáo trộn tên khi cố gắng liên kết với callee.
Peter - Phục hồi Monica

@ PeterA.Schneider: Vâng, cụm từ tiêu đề được phóng đại. Các toàn bộ phần còn lại của câu trả lời có chứa các chi tiết thực tế thích hợp.
Các cuộc đua nhẹ nhàng trong quỹ đạo

21

MSVC trong thực tế không mang tên C, mặc dù trong một thời trang đơn giản. Nó đôi khi nối thêm @4hoặc một số nhỏ khác. Điều này liên quan đến các quy ước gọi và nhu cầu dọn dẹp ngăn xếp.

Vì vậy, tiền đề chỉ là thiếu sót.


2
Đó không thực sự là tên mangling. Nó chỉ đơn giản là một quy ước đặt tên cụ thể của nhà cung cấp (hoặc tên quảng cáo) để ngăn chặn các vấn đề với các tệp thực thi được liên kết với DLL được xây dựng với các hàm có các quy ước gọi khác nhau.
Peter

2
Điều gì về việc chuẩn bị trước với một _?
OrangeDog

12
@Peter: nghĩa đen là điều tương tự.
Các cuộc đua nhẹ nhàng trong quỹ đạo

5
@Frankie_C: "Người gọi dọn dẹp ngăn xếp" không được chỉ định bởi bất kỳ tiêu chuẩn C nào: không quy ước gọi nào là tiêu chuẩn hơn các quy tắc khác từ góc độ ngôn ngữ.
Ben Voigt

2
Và từ góc độ MSVC, "quy ước gọi tiêu chuẩn" chính là thứ bạn chọn /Gd, /Gr, /Gv, /Gz. (Nghĩa là, quy ước gọi tiêu chuẩn là những gì được sử dụng trừ khi một khai báo hàm chỉ định rõ ràng một quy ước gọi.). Bạn đang nghĩ __cdeclđó là quy ước gọi tiêu chuẩn mặc định.
MSalters

13

Rất phổ biến khi có các chương trình được viết một phần bằng C và được viết một phần bằng một số ngôn ngữ khác (thường là ngôn ngữ lắp ráp, nhưng đôi khi là Pascal, FORTRAN hoặc một cái gì đó khác). Các chương trình cũng có các thành phần khác nhau được viết bởi những người khác nhau, những người có thể không có mã nguồn cho mọi thứ.

Trên hầu hết các nền tảng, có một đặc tả - thường được gọi là ABI [Giao diện nhị phân ứng dụng] mô tả những gì trình biên dịch phải làm để tạo ra một hàm với một tên cụ thể chấp nhận đối số của một số loại cụ thể và trả về giá trị của một loại cụ thể. Trong một số trường hợp, ABI có thể định nghĩa nhiều hơn một "quy ước gọi"; trình biên dịch cho các hệ thống như vậy thường cung cấp một phương tiện cho biết nên sử dụng quy ước gọi nào cho một chức năng cụ thể. Ví dụ, trên Macintosh, hầu hết các thường trình trong Hộp công cụ đều sử dụng quy ước gọi Pascal, do đó nguyên mẫu cho một cái gì đó như "LineTo" sẽ giống như:

/* Note that there are no underscores before the "pascal" keyword because
   the Toolbox was written in the early 1980s, before the Standard and its
   underscore convention were published */
pascal void LineTo(short x, short y);

Nếu tất cả các mã trong một dự án được biên dịch bằng cùng một trình biên dịch, việc trình biên dịch xuất ra cho mỗi hàm sẽ không thành vấn đề, nhưng trong nhiều trường hợp, mã C sẽ gọi các hàm được biên dịch bằng các công cụ khác và không thể được biên dịch lại với trình biên dịch hiện tại [và rất có thể thậm chí không có trong C]. Do đó, việc xác định tên của trình liên kết là rất quan trọng đối với việc sử dụng các chức năng đó.


Vâng, đó là câu trả lời. Nếu nó chỉ là C và C ++ thì thật khó hiểu tại sao nó lại được thực hiện theo cách đó. Để hiểu chúng ta phải đặt mọi thứ trong bối cảnh của cách liên kết tĩnh cũ. Liên kết tĩnh có vẻ nguyên thủy đối với các lập trình viên Windows nhưng đó là lý do chính khiến C không thể đặt tên.
user34660

2
@ user34660: Không phải quất. Đó là lý do mà C không thể bắt buộc sự tồn tại của các tính năng mà việc triển khai sẽ yêu cầu nhập tên xáo trộn hoặc cho phép tồn tại nhiều biểu tượng giống như tên được phân biệt bởi các đặc điểm phụ.
supercat

chúng ta có biết rằng đã có những nỗ lực "ủy thác" những thứ như vậy hoặc những thứ đó là những phần mở rộng có sẵn cho C trước C ++?
user34660

@ user34660: Re "Liên kết tĩnh có vẻ nguyên thủy đối với các lập trình viên Windows ...", nhưng liên kết động đôi khi có vẻ giống như một PITA chính đối với những người sử dụng Linux, khi cài đặt chương trình X (có thể được viết bằng C ++) có nghĩa là phải theo dõi và cài đặt các phiên bản cụ thể của các thư viện mà bạn đã có các phiên bản khác nhau trên hệ thống của mình.
jamesqf

@jamesqf, vâng, Unix không có liên kết động trước Windows. Tôi biết rất ít về liên kết động trong Unix / Linux nhưng có vẻ như nó không liền mạch như trong hệ điều hành nói chung.
dùng34660

12

Tôi sẽ thêm một câu trả lời khác, để giải quyết một số cuộc thảo luận tiếp tuyến đã diễn ra.

C ABI (giao diện nhị phân ứng dụng) ban đầu được gọi để truyền các đối số trên ngăn xếp theo thứ tự ngược lại (nghĩa là - được đẩy từ phải sang trái), trong đó người gọi cũng giải phóng bộ lưu trữ ngăn xếp. ABI hiện đại thực sự sử dụng các thanh ghi để truyền các đối số, nhưng nhiều cân nhắc xáo trộn quay trở lại đối số ngăn xếp ban đầu đó.

Ngược lại, Pascal ABI ban đầu đã đẩy các đối số từ trái sang phải và callee phải bật các đối số. C ABI ban đầu vượt trội so với Pascal ABI ban đầu ở hai điểm quan trọng. Thứ tự đẩy đối số có nghĩa là phần bù ngăn xếp của đối số đầu tiên luôn được biết đến, cho phép các hàm có số lượng đối số không xác định, trong đó các đối số đầu kiểm soát có bao nhiêu đối số khác (alaprintf ).

Cách thứ hai mà C ABI vượt trội là hành vi trong trường hợp người gọi và callee không đồng ý về việc có bao nhiêu đối số. Trong trường hợp C, miễn là bạn không thực sự truy cập các đối số qua câu hỏi cuối cùng, không có gì xấu xảy ra. Trong Pascal, số lượng đối số sai được bật ra từ ngăn xếp và toàn bộ ngăn xếp bị hỏng.

Windows 3.1 ABI ban đầu được dựa trên Pascal. Như vậy, nó đã sử dụng Pascal ABI (các đối số theo thứ tự từ trái sang phải, callee bật lên). Vì bất kỳ sự không phù hợp nào trong số đối số có thể dẫn đến tham nhũng ngăn xếp, một sơ đồ xáo trộn đã được hình thành. Mỗi tên hàm được xáo trộn với một số chỉ kích thước, tính bằng byte, của các đối số của nó. Vì vậy, trên máy 16 bit, hàm sau (cú pháp C):

int function(int a)

Được đọc sai function@2, vì intrộng hai byte. Điều này đã được thực hiện để nếu khai báo và định nghĩa không khớp, trình liên kết sẽ không tìm thấy hàm thay vì làm hỏng ngăn xếp trong thời gian chạy. Ngược lại, nếu chương trình liên kết, thì bạn có thể chắc chắn số byte chính xác được bật ra từ ngăn xếp ở cuối cuộc gọi.

Windows 32 bit trở đi sử dụng stdcall ABI thay thế. Nó tương tự như Pascal ABI, ngoại trừ thứ tự đẩy giống như trong C, từ phải sang trái. Giống như Pascal ABI, tên xáo trộn kích thước byte đối số vào tên hàm để tránh tham nhũng ngăn xếp.

Không giống như các khiếu nại được đưa ra ở nơi khác, C ABI không xáo trộn các tên hàm, ngay cả trên Visual Studio. Ngược lại, các hàm xáo trộn được trang trí với stdcallđặc tả ABI không phải là duy nhất đối với VS. GCC cũng hỗ trợ ABI này, ngay cả khi biên dịch cho Linux. Điều này được Wine sử dụng rộng rãi , sử dụng trình tải riêng của nó để cho phép chạy thời gian liên kết các tệp nhị phân được biên dịch Linux với các tệp DLL được biên dịch của Windows.


9

Trình biên dịch C ++ sử dụng xáo trộn tên để cho phép các tên ký hiệu duy nhất cho các hàm bị quá tải mà chữ ký của nó sẽ giống nhau. Về cơ bản, nó cũng mã hóa các loại đối số, cho phép đa hình hóa ở mức độ dựa trên chức năng.

C không yêu cầu điều này vì nó không cho phép quá tải các chức năng.

Lưu ý rằng việc xáo trộn tên là một (nhưng chắc chắn không phải là lý do duy nhất!) Mà người ta không thể dựa vào 'C ++ ABI'.


8

C ++ muốn có khả năng tương tác với mã C liên kết với nó hoặc liên kết với nó.

C mong đợi các tên hàm không được đặt tên.

Nếu C ++ đọc sai nó, nó sẽ không tìm thấy các hàm không được xáo trộn từ C, hoặc C sẽ không tìm thấy các hàm C ++ được xuất. Trình liên kết C phải có được tên mà nó mong đợi, vì nó không biết nó đến từ hoặc đi đến C ++.


3

Việc xáo trộn tên của các hàm và biến C sẽ cho phép các kiểu của chúng được kiểm tra tại thời điểm liên kết. Hiện tại, tất cả các triển khai C (?) Cho phép bạn xác định một biến trong một tệp và gọi nó là một hàm trong một tệp khác. Hoặc bạn có thể khai báo một hàm có chữ ký sai (ví dụ void fopen(double)và sau đó gọi nó.

Tôi đã đề xuất một sơ đồ cho mối liên kết an toàn kiểu của các biến và hàm C thông qua việc sử dụng xáo trộn trở lại vào năm 1991. Lược đồ này không bao giờ được thông qua, bởi vì, như đã lưu ý ở đây, điều này sẽ phá hủy khả năng tương thích ngược.


1
Bạn có nghĩa là "cho phép các loại của họ được kiểm tra tại thời điểm liên kết ". Các loại được kiểm tra tại thời điểm biên dịch, nhưng liên kết với các tên không được trộn lẫn có thể kiểm tra xem các khai báo được sử dụng trong các đơn vị biên dịch khác nhau có đồng ý hay không. Và nếu họ không đồng ý, thì hệ thống xây dựng của bạn đã bị hỏng cơ bản và cần được sửa chữa.
cmaster - phục hồi monica
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.