Mục §6.5.3.2 "Địa chỉ và gián tiếp khai thác" ¶3 nói (phần có liên quan chỉ):tiêu chuẩn C giải quyết đơn giản hóa mâu thuẫn
Các & hành unary trả về địa chỉ của toán hạng của nó. ... Nếu toán hạng là kết quả của toán tử
*
unary, toán tử&
được đánh giá và kết quả là nếu cả hai bị bỏ qua, ngoại trừ các ràng buộc trên toán tử vẫn áp dụng và kết quả không phải là lvalue. Tương tự, nếu các toán hạng là kết quả của một nhà điều hành[]
, cả&
điều hành cũng không phải là unary*
được ngụ ý bởi[]
được đánh giá và kết quả là, nếu như các nhà điều hành&
đã được gỡ bỏ và các nhà điều hành[]
được thay đổi thành một nhà điều hành+
. ...
Điều này có nghĩa rằng đây:
#define NUM 10
int tmp[NUM];
int *i = tmp;
printf("%ti\n", (ptrdiff_t) (&*i - i));
printf("%ti\n", (ptrdiff_t) (&i[NUM] - i));
có nên hoàn toàn hợp pháp, in 0 và NUM
(10). Tiêu chuẩn này có vẻ rất rõ ràng rằng cả hai trường hợp này đều được yêu cầu phải được tối ưu hóa.
Tuy nhiên, nó dường như không đòi hỏi những điều sau đây để được tối ưu hóa:
struct { int a; short b; } tmp, *s = tmp;
printf("%ti\n", (ptrdiff_t) (&s->b - s));
Điều này có vẻ hết sức mâu thuẫn. Tôi có thể thấy không có lý do gì mà mã trên không nên in sizeof(int)
cộng với (không) đệm (có thể là 4).
Đơn giản hóa biểu thức &->
sẽ giống như khái niệm (IMHO) là &[]
, một địa chỉ đơn giản-cộng-bù. Nó thậm chí là một bù đắp mà sẽ được xác định tại thời gian biên dịch, chứ không phải là thời gian chạy tiềm năng với các nhà điều hành []
.
Có điều gì lý do tại sao điều này dường như không nhất quán?
Tôi đã nhìn thấy rất nhiều câu hỏi về tiêu chuẩn C và C++ mà tôi không biết cách làm bất cứ điều gì nhưng đề cao, yêu thích và chờ đợi để đọc câu trả lời. Nó cảm thấy kỳ lạ để thực sự đã viết một. –
thú vị ... Bản in MSVC++ 4! – Abhi
@Abhi Rao - GCC (4.0) với -Wall -Wextra -Werror biên dịch và in 4 mà không có khiếu nại. –