Tôi nghĩ rằng một cái gì đó đang bị bỏ lỡ bởi các câu trả lời khác.
Có, p[i]
theo định nghĩa tương đương với *(p+i)
, mà (vì bổ sung là giao hoán) tương đương với *(i+p)
, mà (một lần nữa, theo định nghĩa của []
toán tử) là tương đương với i[p]
.
(Và trong array[i]
, tên mảng được chuyển đổi hoàn toàn thành một con trỏ thành phần tử đầu tiên của mảng.)
Nhưng tính giao hoán của bổ sung không phải là tất cả rõ ràng trong trường hợp này.
Khi cả hai toán hạng đều cùng loại hoặc thậm chí là các loại số khác nhau được thăng cấp thành một loại phổ biến, giao hoán có ý nghĩa hoàn hảo : x + y == y + x
.
Nhưng trong trường hợp này, chúng ta đang nói cụ thể về số học con trỏ, trong đó một toán hạng là một con trỏ và cái còn lại là một số nguyên. (Số nguyên + số nguyên là một hoạt động khác nhau và con trỏ + con trỏ là vô nghĩa.)
Mô tả của tiêu chuẩn C về +
toán tử ( N1570 6.5.6) cho biết:
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 hoàn chỉnh và một toán hạng khác sẽ có kiểu số nguyên.
Nó có thể dễ dàng như đã nói:
Ngoài ra, cả hai toán hạng sẽ có kiểu số học hoặc
toán hạng bên trái sẽ là một con trỏ tới một loại đối tượng hoàn chỉnh và toán hạng bên phải
sẽ có kiểu số nguyên.
trong trường hợp cả hai i + p
và i[p]
sẽ là bất hợp pháp.
Theo thuật ngữ C ++, chúng tôi thực sự có hai bộ +
toán tử quá tải , có thể được mô tả một cách lỏng lẻo là:
pointer operator+(pointer p, integer i);
và
pointer operator+(integer i, pointer p);
trong đó chỉ có đầu tiên là thực sự cần thiết.
Vậy tại sao nó lại theo cách này?
C ++ đã kế thừa định nghĩa này từ C, lấy từ B (tính giao hoán của việc lập chỉ mục mảng được đề cập rõ ràng trong Tài liệu tham khảo của người dùng năm 1972 đến B ), lấy từ BCPL (hướng dẫn sử dụng ngày 1967) ngôn ngữ trước đó (CPL? Algol?).
Vì vậy, ý tưởng rằng lập chỉ mục mảng được xác định theo thuật ngữ cộng, và phép cộng đó, thậm chí cả con trỏ và số nguyên, có tính giao hoán, quay trở lại nhiều thập kỷ, theo ngôn ngữ tổ tiên của C.
Những ngôn ngữ đó được gõ ít mạnh hơn nhiều so với C hiện đại. Cụ thể, sự khác biệt giữa con trỏ và số nguyên thường bị bỏ qua. (Lập trình viên C sớm đôi khi được dùng con trỏ như số nguyên unsigned, trước khi unsigned
từ khóa đã được thêm vào ngôn ngữ.) Vì vậy, ý tưởng thực hiện Ngoài ra phi giao hoán vì các toán hạng là các loại khác nhau có lẽ sẽ không xảy ra cho các nhà thiết kế trong những ngôn ngữ. Nếu người dùng muốn thêm hai "thứ", cho dù những "thứ đó" là số nguyên, con trỏ hay thứ gì khác, thì đó không phải là ngôn ngữ để ngăn chặn nó.
Và trong nhiều năm qua, bất kỳ thay đổi nào đối với quy tắc đó sẽ phá vỡ mã hiện có (mặc dù tiêu chuẩn ANSI C năm 1989 có thể là một cơ hội tốt).
Thay đổi C và / hoặc C ++ để yêu cầu đặt con trỏ ở bên trái và số nguyên ở bên phải có thể phá vỡ một số mã hiện có, nhưng sẽ không mất sức mạnh biểu cảm thực sự.
Vì vậy, bây giờ chúng ta có arr[3]
và 3[arr]
có nghĩa chính xác điều tương tự, mặc dù hình thức sau không bao giờ xuất hiện bên ngoài IOCCC .