Một con trỏ đến một loại không đầy đủ có thể không đầy đủ?


9

Có thể int (*)[]là một loại không đầy đủ?

C 2018 6.2.5 1 nói:

Tại các điểm khác nhau trong một đơn vị dịch thuật, một loại đối tượng có thể không đầy đủ (thiếu thông tin đầy đủ để xác định kích thước của các đối tượng của loại đó) hoặc đầy đủ (có đủ thông tin).

Do đó, dường như nếu kích thước của một loại được biết đến, loại đã hoàn thành. 6.2.6.1 28 chỉ định rằng một số loại con trỏ nhất định phải có cùng kích thước (con trỏ tới voidvà ký tự, con trỏ tới loại tương thích, con trỏ tới cấu trúc và con trỏ tới kết hợp), nhưng con trỏ tới các loại khác có thể khác nhau.

Trong một triển khai C trong đó tất cả các con trỏ hoặc tất cả các con trỏ tới các mảng intđều có cùng kích thước, thì kích thước int (*)[]được biết đến, vì vậy nó sẽ hoàn thành. Trong một triển khai, giả sử, sử dụng các con trỏ khác nhau cho các mảng lớn, kích thước sẽ không được biết đến, vì vậy nó không đầy đủ.

Như MM chỉ ra , cấu trúc không được chứa thành viên có loại không hoàn chỉnh, ngoại trừ thành viên mảng linh hoạt cuối cùng, theo một ràng buộc trong 6.7.2.1 3. Điều này cho thấy rằng việc triển khai với một kích thước con trỏ phải chấp nhận struct { int (*p)[]; }trong khi việc triển khai có khác kích thước cho các mảng như vậy phải chẩn đoán vi phạm ràng buộc. (Điều này có nghĩa là một tuyên bố như vậy không phải là một phần của việc tuân thủ nghiêm ngặt C.)


6.2.5 (p22) giúp đỡ? (hoặc có thêm sự nhầm lẫn nào cho phép loại không đầy đủ được hoàn thành bằng cách khai báo sau không?)
David C. Rankin

@ DavidC.Rankin Trong 6.2.5 / 20, người ta thậm chí còn nói rằng con trỏ luôn là loại hoàn chỉnh
Barshe

@L LanguageLawyer: Làm thế nào điều đó có liên quan? Câu hỏi đặt ra là Có một chữ X không phải là chữ Y không, có phải là chữ X có chữ Y không?
Eric Postpischil

@L LanguageLawyer: Thực tế void *là hoàn thành cho thấy một con trỏ đến một loại không hoàn chỉnh có thể được hoàn thành. Nó không hiển thị liệu một con trỏ tới một loại không hoàn chỉnh có thể không đầy đủ hay không. Nếu người ta hỏi có thể một động vật có vú là một con voi không? Câu hỏi hỏi liệu bộ X của con trỏ thành loại không hoàn chỉnh có thể chứa một phần tử không đầy đủ không. Cho thấy tập hợp X của con trỏ thành kiểu không hoàn chỉnh chứa một phần tử hoàn chỉnh là không liên quan.
Eric Postpischil

@EricPostpischil Rất tiếc. Tôi đã đọc sai tiêu đề là "Con trỏ tới loại không hoàn chỉnh có thể hoàn thành không?"
Luật sư ngôn ngữ

Câu trả lời:


3

Một mảng có kích thước không xác định là không đầy đủ:

Một kiểu mảng có kích thước không xác định là một kiểu không đầy đủ. Nó được hoàn thành, đối với một định danh loại đó, bằng cách chỉ định kích thước trong một khai báo sau (với liên kết bên trong hoặc bên ngoài).

int (*)[]Tuy nhiên, loại không đầy đủ: Đó là một con trỏ của một mảng có intkích thước không xác định.
Và một con trỏ có kích thước nổi tiếng:

printf ("Size %d\n", sizeof(int (*)[]));

6.2.5 / 23: Một loại có kích thước không đổi đã biết nếu loại không đầy đủ và không phải là loại mảng có chiều dài thay đổi.

Hơn nữa, bạn thậm chí có thể hủy đăng ký nó, nhờ vào ngữ nghĩa mảng:

typedef int (*T)[];
...
int a[10];
for (int i=0; i<10; i++) a[i]=i;
T p=a;
for (int i=0; i<10; i++) printf ("%d ",(*p)[i]);
printf ("\n");

Biên tập

Ngoài ra, một con trỏ luôn là một loại hoàn chỉnh. Nó được viết màu đen trên nền trắng trong 6.2.5 / 20:

Một loại con trỏ có thể được bắt nguồn từ một loại chức năng hoặc một loại đối tượng, được gọi là loại tham chiếu. Một loại con trỏ mô tả một đối tượng có giá trị cung cấp một tham chiếu đến một thực thể của loại được tham chiếu. Một loại con trỏ xuất phát từ loại T được tham chiếu đôi khi được gọi là '' con trỏ tới T ''. Việc xây dựng một loại con trỏ từ một loại tham chiếu được gọi là '' dẫn xuất loại con trỏ ''. Một loại con trỏ là một loại đối tượng hoàn chỉnh.


Tôi nghĩ rằng bạn đã đun sôi nó và gcc đồng ý. struct w / con trỏ đến mảng không đầy đủ tương tự như câu hỏi ban đầu nhắc nhở cuộc thảo luận.
David C. Rankin

Chỉ có đoạn cuối là có liên quan. Ví dụ printfchỉ cho thấy rằng một con trỏ tới một mảng chưa hoàn thành đã hoàn thành trong quá trình thực thi mà nó đã được thực thi, như đã nêu trong câu hỏi nếu không phải là 6.2.5 20, được trích dẫn trong đoạn cuối, nó có thể không biên dịch được. 6.2.5 23 cũng không liên quan; nó cho chúng ta biết kích thước được biết và không đổi nếu nó hoàn thành và chúng ta đã biết rằng việc hoàn thành có nghĩa là kích thước được biết đến.
Eric Postpischil

6.2.5 20 thật thú vị. Tôi suy đoán rằng nó không có ý định gây ra hậu quả này, nhưng điều đó có nghĩa là tất cả các con trỏ để hoàn thành các loại có cùng loại khi không đầy đủ phải có cùng kích thước. Ví dụ, tất cả các con trỏ tới các mảng intphải có cùng kích thước với nhau và tất cả các con trỏ tới các mảng của một số nhất định structphải có cùng kích thước với nhau, mặc dù có lẽ không phải tất cả các con trỏ tới các mảng thuộc các loại khác nhau structđều có cùng kích thước như nhau.
Eric Postpischil

1
@EricPostpischil có thể là văn bản "Tương tự, con trỏ tới các phiên bản đủ điều kiện hoặc không đủ tiêu chuẩn của các loại tương thích sẽ có cùng yêu cầu đại diện và căn chỉnh." nên được giải thích để nói rằng T(*)[]phải có cùng kích thước T(*)[5], vì chúng là loại tương thích và chúng tôi có thể thêm hoặc xóa vòng loại
MM

Việc cho phép các loại tương thích có kích thước khác nhau sẽ dẫn đến một loạt vấn đề, có lẽ đó là một khiếm khuyết mà tiêu chuẩn không loại trừ rõ ràng
MM
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.