Chúng ta sẽ xét 1 số ví dụ mình họa cho quy tắc tính toán địa chỉ vừa được trình bày. Hình trên trình bày một ví dụ về tính toán địa chỉ con trỏ và các ký pháp lúc viết chương trình. Con trỏ p kiểu double nhận địa chỉ của biến a[1] là phần tử thứ hai trong mảng năm số. Vì p = &a[1] và đang dùng cùng kiểu double nên theo quy ước ký pháp ở bài trước thì *p, p[0], và a[1] là cùng 1 biến, tức là mặc dù viết khác nhưng chúng tham chiếu đến cùng 1 ô nhớ 8-byte(kích thước biến double) có thể chứa một số thực kiểu double. Địa chỉ p + 1 dời đi so với p một độ dời bằng với 1 x sizeof(double) = 8 byte, nên p + 1 cũng là &a[2], do đó *(p + 1), p[1], a[2] là ba cách viết khác nhau cùng tham chiếu đến cùng một biến. Tương tự *(p + 3), p[3], a[4] cũng tham chiếu đến cùng 1 biến a[4].
Địa chỉ (float*)p + 4 là một con trỏ kiểu float* dời đi so với p một độ dời là 4 x sizeof(float) = 16 byte = 2 x (8 byte). Do đó vì p đang giữ địa chỉ của a[1] nên (float*)p + 4 bằng với: địa chỉ (a[1]) + 16 byte và trùng với địa chỉ của a[3]. Tuy nhiên ký pháp biến *((float*)p + 4) (một biến float kích thước 4-byte) vô nghĩa vì tương đương với phân nửa của biến a[3] (một biến double kích thước 8-byte). Nếu ép kiểu để chuyển về double như là *(double*)((float*)p + 4) thì chính là biến a[3], cũng cùng nghĩa với *(p + 2).
Địa chỉ (float*)p + 4 là một con trỏ kiểu float* dời đi so với p một độ dời là 4 x sizeof(float) = 16 byte = 2 x (8 byte). Do đó vì p đang giữ địa chỉ của a[1] nên (float*)p + 4 bằng với: địa chỉ (a[1]) + 16 byte và trùng với địa chỉ của a[3]. Tuy nhiên ký pháp biến *((float*)p + 4) (một biến float kích thước 4-byte) vô nghĩa vì tương đương với phân nửa của biến a[3] (một biến double kích thước 8-byte). Nếu ép kiểu để chuyển về double như là *(double*)((float*)p + 4) thì chính là biến a[3], cũng cùng nghĩa với *(p + 2).
Nhận xét
Đăng nhận xét