Tại sao các cấu trúc đóng gói không phải là một phần của ngôn ngữ C?


10

Mỗi trình biên dịch C cung cấp tùy chọn "đóng gói" các cấu trúc C (ví dụ: __attribute__ ((__packed__))hoặc #pragma pack()). Bây giờ, tất cả chúng ta đều biết rằng việc đóng gói là bắt buộc, nếu chúng ta muốn gửi hoặc lưu trữ dữ liệu một cách đáng tin cậy. Đây cũng phải là một yêu cầu kể từ những ngày đầu tiên của ngôn ngữ C.

Vì vậy, tôi tự hỏi tại sao cấu trúc đóng gói không phải là một phần của đặc tả ngôn ngữ C? Họ thậm chí không ở C99 hay C11 mặc dù sự cần thiết phải có chúng trong nhiều thập kỷ nay? Tôi đang thiếu gì? Tại sao nó là trình biên dịch cụ thể?


2
Họ không cần thiết phải viết mã C thuần túy.
dùng253751

Câu trả lời:


7

Tôi đoán đó là vì nó phụ thuộc vào sự kết hợp của CPU / trình biên dịch đích được sử dụng. Điều này có nghĩa là tốt hơn là trở thành một chỉ thị của trình biên dịch (vì nó liên quan đến điều đó) hơn là một khía cạnh ngôn ngữ, vì làm thế nào để xác định điều đó? Cách duy nhất họ có thể làm là với công đoàn.

Bài viết của Raymond cung cấp một số cái nhìn sâu sắc về lý do tại sao đây là: http://www.catb.org/esr/structure-packing/


Bài viết rất thú vị. (+1)
Giorgio

Khó khăn gì khi cho phép mã nói "Tôi cần một cấu trúc chứa 12 byte; trường X phải hoạt động như một số nguyên 32 bit được lưu dưới dạng bốn octet nhỏ ở cuối 0, trường Y phải hoạt động như một số nguyên 64 bit được lưu trữ dưới dạng octet byte little endian ở offset 4 "? Mã để xử lý điều đó trên bất kỳ nền tảng nào không nên tệ hơn loại trình biên dịch đã có đối với bitfield và trong trường hợp lập trình viên tình cờ xác định căn chỉnh phù hợp với máy gốc có thể hiệu quả hơn nhiều. Trên các máy khác, nó sẽ kém hiệu quả hơn nhưng vẫn có thể mang theo được.
supercat

5

Có ba yếu tố chính.

  1. Một số bộ xử lý không thể truy cập dữ liệu chưa được phân bổ (ví dụ: số nguyên hoặc dấu phẩy bắt đầu trên một địa chỉ lẻ). Cố gắng làm kích hoạt một ngoại lệ.
  2. Một số bộ xử lý có thể truy cập dữ liệu chưa được phân bổ, nhưng với chi phí hiệu năng.
  3. Hầu hết các cấu trúc được truy cập bởi một bộ mã nguồn C / C ++ và khả năng tương tác với các ngôn ngữ khác là ngoại lệ, không phải là quy tắc.

Với các yếu tố này, cả trình biên dịch chuẩn và tất cả các trình biên dịch C / C ++ thường xuyên cấu trúc pad để đảm bảo căn chỉnh tối ưu cho bộ xử lý, nhưng cũng cung cấp các cơ chế để ghi đè lên điều này nếu cần cho mục đích xen kẽ.

Điều này không có nghĩa là một cái gì đó đã bị bỏ qua. Nó được hiểu rất rõ và tình hình hiện tại là do thiết kế. Các phiên bản mới nhất của tiêu chuẩn C ++ có hỗ trợ rộng rãi để xử lý các vấn đề căn chỉnh, có lẽ bạn không quen thuộc.


Bất kỳ đối số nào có thể được thực hiện đối với các cấu trúc đóng gói cũng có thể được sử dụng để biện minh cho việc biến bitfield thành một tính năng tùy chọn. Truy cập các thành viên của các cấu trúc đóng gói sẽ chậm trên một số bộ xử lý, nhanh trên các bộ xử lý khác, nhưng việc các trình biên dịch cố gắng thay thế các cách giải quyết mã người dùng vì thiếu các tính năng truy cập không được phân bổ bằng mã hiệu quả hơn phức tạp hơn nhiều so với việc các trình biên dịch chỉ định họ cần.
supercat

@supercat: bạn đang tranh cãi vì điều gì (hoặc chống lại)? Tôi không hiểu
david.pfx

Tôi cho rằng bitfield nên là tùy chọn, nhưng nếu bitfield sẽ là một tính năng bắt buộc thì sẽ có ý nghĩa khi mở rộng chúng theo cách cho phép kiểm soát rõ ràng bố cục cấu trúc. Mặt khác, hiệu ứng ròng là các trình biên dịch phải thực hiện 90% công việc cần thiết để kiểm soát hoàn toàn bố cục, nhưng các lập trình viên chỉ gặt hái 10% lợi ích.
supercat

@supercat: các trường bit là các số nguyên và tuân theo các quy tắc sắp xếp bố cục bit giống như các số nguyên: triển khai được xác định. Các thành viên cấu trúc được sắp xếp theo ranh giới ký tự như đã khai báo, có thể có đóng gói được chèn vào. Chúng có khái niệm khá riêng biệt. [Bạn sẽ cần hỏi một câu hỏi khác nếu bạn muốn mở rộng đề xuất của mình, nhưng tôi không nghĩ rằng nó sẽ hoạt động cả.]
david.pfx

0

Nó là trình biên dịch cụ thể vì nó không có trong tiêu chuẩn. Và nó không nằm trong tiêu chuẩn vì khó có thể chỉ định theo cách không đòi hỏi nhiều nỗ lực triển khai cho trình biên dịch nền tảng tối nghĩa với các hạn chế căn chỉnh được thi hành.

Và không có nỗ lực nào có nhiều lý do, bởi vì mọi trình biên dịch / nền tảng mà bất kỳ ai sử dụng trình biên dịch C89 trở lên đều quan tâm đã thực hiện.


2
??? Bạn đã trả lời cho câu hỏi "Tại sao không phải là ngôn ngữ tiêu chuẩn" bằng cách nói "bởi vì không phải là tiêu chuẩn" ...
Emilio Garavaglia

Đó là những gì tôi nghĩ đầu tiên, nhưng sau đó, một lần nữa, người ta có thể chỉ định tính năng như "nếu struct được xác định bằng từ khóa 'đóng gói' thì kích thước của nó được đảm bảo giống với kích thước được thêm của từng thành viên. Trên các nền tảng không hỗ trợ truy cập bộ nhớ không được phân bổ, truy cập vào một trong các giá trị thành viên cấu trúc là hành vi không xác định. " Điều này sẽ cho phép các nhà phát triển trên các nền tảng mà không có quyền truy cập không được chỉ định để biết ít nhất là biết kích thước cấu trúc và phần bù của từng thành viên riêng lẻ ...
grasbueschel

1
Có thể làm cho truy cập không được phân bổ hoạt động trên các hệ thống không hỗ trợ phần cứng bằng cách triển khai các cấu trúc đó như một mảng byte và thực hiện các thao tác và &/ dịch chuyển bit cần thiết |để đọc / ghi các giá trị của từng trường.
dan04

1
@ dan04: Trên nhiều bộ xử lý, trình biên dịch có thể tạo mã để truy cập không được phân bổ hiệu quả hơn so với sử dụng chuỗi các lần đọc và dịch chuyển byte. Có một cú pháp cho điều đó sẽ giúp các trình biên dịch như vậy dễ dàng tạo mã hiệu quả hơn là yêu cầu chúng nhận ra tất cả các cách khác nhau mà các lập trình viên có thể cố gắng viết mã để tập hợp các byte thành các kiểu dài hơn.
supercat
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.