Theo N1570 (C11 dự thảo) 6.5.6/8
khai thác Additive:Lý do cơ bản cho một phần tử cuối cùng của một đối tượng mảng là gì?
Hơn nữa, nếu biểu thức
P
điểm đến yếu tố cuối cùng của một đối tượng mảng , khái niệm(P)+1
điểm một quá khứ yếu tố cuối cùng của đối tượng mảng và nếu biểu thứcQ
điểm vượt qua phần tử cuối của đối tượng mảng, biểu thức(Q)-1
trỏ đến phần tử cuối cùng của đối tượng mảng
phân lớp 6.5.6/9
cũng chứa:
Hơn nữa, nếu biểu thức
P
điểm hoặc để một phần tử của một mảng đối tượng hoặc một quá khứ yếu tố cuối cùng của một đối tượng mảng, và các biểu hiệnQ
điểm đến phần tử cuối cùng của cùng một đối tượng mảng, biểu thức((Q)+1)-(P)
có cùng giá trị với((Q)-(P))+1
và là-((P)-((Q)+1))
và có giá trị bằng 0 nếu biểu thứcP
chỉ một phần tử cuối cùng của đối tượng mảng, mặc dù biểu thức(Q)+1
không trỏ đến một phần tử của đối tượng mảng. 106)
này biện minh cho số học con trỏ của như thế này mới có giá trị:
#include <stdio.h>
int main(void)
{
int a[3] = {0, 1, 2};
int *P, *Q;
P = a + 3; // one past the last element
Q = a + 2; // last element
printf("%td\n", ((Q)+1)-(P));
printf("%td\n", ((Q)-(P))+1);
printf("%td\n", -((P)-((Q)+1)));
return 0;
}
tôi mong chờ để không cho phép trỏ đến phần tử của mảng out-of-bounds, mà dereference hoạt động hành vi như không xác định (mảng tràn), do đó nó làm cho nó có khả năng nguy hiểm. Có lý do nào cho việc này không?
"Tôi hy vọng sẽ không cho phép trỏ đến phần tử của mảng ngoài giới hạn, mà hành vi dereference đóng vai trò là hành vi không xác định". Dereferencing yếu tố này không được phép nên không có vấn đề gì. "Có lý do nào cho việc này không?" Có, quá nhiều để liệt kê. Google cho * phạm vi nửa mở trong C *. –
C không (bình thường) thực hiện kiểm tra giới hạn, vì vậy mã sẽ biên dịch tốt. Tuy nhiên, việc truy cập bộ nhớ bên ngoài giới hạn của mục đang được truy cập là hành vi không xác định và có thể/sẽ dẫn đến sự kiện lỗi seg. – user3629249