2015-08-07 15 views
14

Nếu bạn sử dụng extern C với tệp C++, điều đó có cho phép hành vi C được xác định không được xác định trong C++ không?Có extern C với C + + tránh hành vi không xác định đó là hợp pháp trong C nhưng không C + +?

blah.h

extern "C" 
{ 
     struct x { 
      int blah; 
      char buf[]; 
     }; 

     char * get_buf(struct x * base); 
     struct x * make_struct(int blah, int size); 
} 

some_random.cpp

#include "blah.h" 

... 

x * data=make_struct(7, 12); 
std::strcpy(get_buf(data), "hello"); 

Đang sử dụng các hành vi quy định tại thành viên mảng linh hoạt C, hành vi được xác định khi được sử dụng theo cách này?

+0

Xem bên dưới, nhưng FAM thường biên dịch chính xác trong C++. – Jason

+0

Lưu ý: Vì 'get_buf() make_struct()' chỉ sử dụng một con trỏ tới 'struct x', tại sao' struct x' được định nghĩa trong 'blah.h'? – chux

+0

Tôi đang chuyển câu hỏi này về phiên bản trước. Nếu bạn có câu hỏi mới, bạn có thể yêu cầu [ask] (http://stackoverflow.com/questions/ask), nhưng chỉnh sửa cuối cùng của bạn dường như là một nỗ lực để vô hiệu tất cả các câu trả lời bạn nhận được. –

Trả lời

18

Thành viên mảng linh hoạt là tính năng tiêu chuẩn của C, bắt đầu với tiêu chuẩn 1999. Chúng không tồn tại trong C++.

Mã của bạn không hợp lệ C++. Gói nó trong extern "C" không thay đổi điều đó. Trình biên dịch C++ phù hợp phải ít nhất là cảnh báo về nó và được cho là nên từ chối nó.

Điều đó xảy ra khi g ++ triển khai thành viên mảng linh hoạt kiểu C dưới dạng phần mở rộng cho C++. Điều đó hoàn toàn hợp pháp (các trình biên dịch được phép thực hiện các phần mở rộng), nhưng việc sử dụng nó không phải là di động. Hành vi của nó, giống như của bất kỳ phần mở rộng ngôn ngữ nào, được định nghĩa bởi trình biên dịch, không phải bởi ngôn ngữ.

Nếu bạn biên dịch nó với g++ -pedantic, bạn sẽ nhận được một cảnh báo:

c.cpp:5:21: warning: ISO C++ forbids zero-size array ‘buf’ [-Wpedantic] 
      char buf[]; 
        ^

Nếu bạn muốn sử dụng C-phong cách thành viên mảng linh hoạt trong một chương trình C++ mà không dựa vào một phần mở rộng trình biên dịch cụ thể, bạn có thể biên dịch mã C của bạn thành C và liên kết nó với chương trình C++ của bạn. Bạn không thể tạo kiểu với thành phần mảng linh hoạt hiển thị cho mã C++ của bạn, nhưng bạn có thể sử dụng nó trong nội bộ mã C, và có thể cung cấp truy cập vào nó trong mã C++ của bạn thông qua một con trỏ đục. Xem the C++ FAQ để biết thông tin về trộn C và C++ trong cùng một chương trình. (Hoặc bạn chỉ có thể sử dụng phần mở rộng g ++, với chi phí không thể biên dịch mã của bạn với các trình biên dịch khác.)

(Tôi giả định rằng bạn đang sử dụng g ++).)

+4

Bạn có thể cần ẩn định nghĩa thực tế của struct x khỏi tiêu đề C++ và coi nó như một con trỏ mờ, trừ khi bạn truy cập nó thông qua các hàm C đã xác định. –

+0

@KennyOstrom: Vâng, đó là những gì tôi đã đề xuất (mặc dù không rõ ràng như bạn đã làm). Tôi sẽ cập nhật câu trả lời của mình. –

11

số

extern "C" chỉ là một đặc điểm kỹ thuật liên kết, do đó những biểu tượng kèm theo có thể được liên kết đến từ C. Nó không chuyển biên dịch của bạn để chế độ "C" cho một phần của mã.

+0

@GlennTeitelbaum Không quan trọng: vấn đề là các thành viên mảng linh hoạt không * tồn tại * trong C++. Ngay cả khi chỉ có một trình biên dịch C đã thấy nó được sử dụng (nó không phải là trường hợp, bạn cố gắng 'std :: copy' vào nó), trình biên dịch C++ sẽ bị nghẹt thở trên khai báo của nó một mình. – Quentin

+2

True, linh hoạt mảng thành viên không tồn tại trong tiêu chuẩn C + +, nhưng họ tồn tại trong phương ngữ g ++ của C + +, như là một phần mở rộng trình biên dịch cụ thể. –

10

Tuyên bố extern "C" chỉ ảnh hưởng đến liên kết của các chức năng bên ngoài, do đó việc mang tên không được thực hiện. Nó không có nghĩa là các hàm sẽ được biên dịch bằng các quy tắc của ngôn ngữ C thay vì C++. Nói cách khác, bao gồm mã trong some_random.cpp sẽ không làm cho hành vi của nó được xác định.

-5

Chỉ là ascii cho đến khi trình biên dịch chạy. Vì vậy, bộ tiền xử lý sẽ dán các tệp lại với nhau, sau đó trình biên dịch sẽ xem kết quả là bất kỳ ngôn ngữ nào bạn đã chỉ định.

Nó không phải là thành viên mảng linh hoạt C, đó là tệp văn bản. Hành vi không xác định vẫn còn.

+5

Thiếu điểm; câu hỏi đặt ra là liệu 'extern" C "' có hợp lệ C/C++ bất hợp pháp thành một loại C++ hợp pháp hay không. –

+0

Nó không xảy ra với tôi rằng extern C có thể được mong đợi để đạt được rất nhiều, trong khi xác định ngôn ngữ một tập tin văn bản được xử lý như dường như ném người. Cảm ơn bình luận của bạn. –

Các vấn đề liên quan