Kết luận cuối cùng: số học trên a void*
là bất hợp pháp trong cả C và C ++.
GCC cho phép nó như một phần mở rộng, xem Số học trên void
- và Con trỏ hàm (lưu ý rằng phần này là một phần của chương "Phần mở rộng C" của hướng dẫn sử dụng). Clang và ICC có thể cho phép void*
số học cho các mục đích tương thích với GCC. Các trình biên dịch khác (như MSVC) không cho phép số học trên void*
và GCC không cho phép nó nếu -pedantic-errors
cờ được chỉ định hoặc nếu -Werror-pointer-arith
cờ được chỉ định (cờ này hữu ích nếu cơ sở mã của bạn cũng phải biên dịch với MSVC).
Tiêu chuẩn C nói
Trích dẫn được lấy từ dự thảo n1256.
Mô tả của tiêu chuẩn về trạng thái hoạt động bổ sung:
6.5.6-2: Ngoài ra, cả hai toán hạng sẽ có kiểu số học hoặc một toán hạng sẽ là một con trỏ tới một loại đối tượng và một toán hạng khác sẽ có kiểu nguyên.
Vì vậy, câu hỏi ở đây là liệu void*
con trỏ tới "loại đối tượng" hay tương đương, liệu đó có phải void
là "loại đối tượng" hay không. Định nghĩa cho "loại đối tượng" là:
6.2.5.1: Các loại được phân vùng thành các loại đối tượng (loại mô tả đầy đủ các đối tượng), loại chức năng (loại mô tả chức năng) và loại không đầy đủ (loại mô tả các đối tượng nhưng thiếu thông tin cần thiết để xác định kích thước của chúng).
Và tiêu chuẩn được định nghĩa void
là:
6.2.5-19: void
Loại bao gồm một tập hợp các giá trị trống; nó là một loại không đầy đủ không thể hoàn thành.
Vì void
là một loại không đầy đủ, nó không phải là một loại đối tượng. Do đó, nó không phải là một toán hạng hợp lệ cho một hoạt động bổ sung.
Do đó, bạn không thể thực hiện số học con trỏ trên một void
con trỏ.
Ghi chú
Ban đầu, người ta cho rằng void*
số học được cho phép, vì những phần này của tiêu chuẩn C:
6.2.5-27: Một con trỏ tới void sẽ có cùng
các yêu cầu biểu diễn và căn chỉnh giống như một con trỏ tới một kiểu ký tự.
Tuy nhiên,
Các
yêu cầu đại diện và căn chỉnh tương tự có nghĩa là ngụ ý khả năng thay thế lẫn nhau như các đối số cho các hàm, trả về các giá trị từ các hàm và các thành viên của hiệp hội.
Vì vậy, điều này có nghĩa printf("%s", x)
có cùng ý nghĩa cho dù x
có loại char*
hay không void*
, nhưng điều đó không có nghĩa là bạn có thể thực hiện số học trên a void*
.
Lưu ý của biên tập viên: Câu trả lời này đã được chỉnh sửa để phản ánh kết luận cuối cùng.