Để hiểu về hack này, trước tiên bạn cần hiểu sự khác biệt của con trỏ, nghĩa là, điều gì xảy ra khi hai con trỏ trỏ đến các phần tử của cùng một mảng bị trừ?
Khi một con trỏ bị trừ đi từ một con trỏ khác, kết quả là khoảng cách (được đo bằng các phần tử mảng) giữa các con trỏ. Vì vậy, nếu p
điểm đến a[i]
và q
trỏ đến a[j]
, thì p - q
bằngi - j
.
C11: 6.5.6 Toán tử phụ gia (p9):
Khi hai con trỏ bị trừ , cả hai sẽ trỏ đến các phần tử của cùng một đối tượng mảng hoặc một phần tử qua phần tử cuối cùng của đối tượng mảng; kết quả là sự khác biệt của các chỉ số của hai phần tử mảng . [...].
Nói cách khác, nếu các biểu thức P
và Q
trỏ đến, tương ứng, các phần tử -th i
và j
-th của một đối tượng mảng, biểu thức (P)-(Q)
có giá trịi−j
được cung cấp giá trị phù hợp với một đối tượng thuộc loại ptrdiff_t
.
Bây giờ tôi đang mong đợi rằng bạn nhận thức được việc chuyển đổi tên mảng thành con trỏ, a
chuyển đổi thành con trỏ thành phần tử đầu tiên của mảng a
. &a
là địa chỉ của toàn bộ khối bộ nhớ, tức là nó là một địa chỉ của mảng a
. Hình dưới đây sẽ giúp bạn hiểu ( đọc câu trả lời này để được giải thích chi tiết ):
Điều này sẽ giúp bạn hiểu rằng tại sao a
và &a
có cùng địa chỉ và (&a)[i]
địa chỉ của mảng thứ i (có cùng kích thước với địa chỉ củaa
).
Vì vậy, tuyên bố
return (&a)[n] - a;
tương đương với
return (&a)[n] - (&a)[0];
và sự khác biệt này sẽ đưa ra số lượng phần tử giữa các con trỏ (&a)[n]
và (&a)[0]
, là n
các mảng từng n
int
phần tử. Do đó, tổng các phần tử mảng là n*n
= n
2 .
GHI CHÚ:
C11: 6.5.6 Toán tử phụ gia (p9):
Khi hai con trỏ bị trừ, cả hai sẽ trỏ đến các phần tử của cùng một đối tượng mảng hoặc một phần tử qua phần tử cuối cùng của đối tượng mảng ; kết quả là sự khác biệt của các chỉ số của hai phần tử mảng. Kích thước của kết quả được xác định theo thực hiện và loại của nó (một kiểu số nguyên đã ký) được ptrdiff_t
xác định trong <stddef.h>
tiêu đề. Nếu kết quả không thể biểu diễn trong một đối tượng thuộc loại đó, thì hành vi không được xác định.
Vì (&a)[n]
không trỏ đến các phần tử của cùng một đối tượng mảng và cũng không đi qua phần tử cuối cùng của đối tượng mảng, (&a)[n] - a
sẽ gọi hành vi không xác định .
Cũng lưu ý rằng, tốt hơn để thay đổi kiểu trả về của hàm p
để ptrdiff_t
.