Vâng, tôi phải thêm một cái gì đó là tốt. Cấu trúc hơi khác so với mảng vì mảng là con trỏ còn cấu trúc thì không. Vì vậy, hãy cẩn thận!
Hãy nói rằng tôi viết đoạn mã vô dụng này:
#include <stdio.h>
typedef struct{
int km;
int kph;
int kg;
} car;
int main(void){
car audi = {12000, 230, 760};
car *ptr = &audi;
}
Ở đây con trỏ trỏ ptr
đến địa chỉ ( ! ) Của biến cấu trúc audi
nhưng bên cạnh cấu trúc địa chỉ cũng có một đoạn dữ liệu ( ! )! Thành viên đầu tiên của khối dữ liệu có cùng địa chỉ với cấu trúc và bạn có thể lấy dữ liệu đó chỉ bằng cách hủy bỏ một con trỏ như thế này *ptr
(không có dấu ngoặc nhọn) .
Nhưng nếu bạn muốn acess bất kỳ thành viên khác so với cái đầu tiên, bạn cần phải thêm một vấn thiết kế như .km
, .kph
, .kg
đó là không có gì hơn offsets đến địa chỉ cơ sở của đoạn dữ liệu ...
Nhưng vì sự preceedence bạn không thể viết *ptr.kg
như toán tử truy cập .
được đánh giá trước khi toán tử tham chiếu *
và bạn sẽ nhận được *(ptr.kg)
đó là không thể như con trỏ không có thành viên! Và trình biên dịch biết điều này và do đó sẽ đưa ra một lỗi, ví dụ:
error: ‘ptr’ is a pointer; did you mean to use ‘->’?
printf("%d\n", *ptr.km);
Thay vào đó, bạn sử dụng cái này (*ptr).kg
và bạn buộc trình biên dịch phải loại bỏ con trỏ thứ nhất và cho phép truy cập vào khối dữ liệu và thứ 2 bạn thêm một phần bù (chỉ định) để chọn thành viên.
Kiểm tra hình ảnh này tôi đã thực hiện:
Nhưng nếu bạn có các thành viên lồng nhau, cú pháp này sẽ trở nên không thể đọc được và do đó ->
được giới thiệu. Tôi nghĩ rằng khả năng đọc là lý do chính đáng duy nhất để sử dụng nó vì điều này ptr->kg
dễ viết hơn nhiều so với(*ptr).kg
.
Bây giờ hãy để chúng tôi viết điều này khác nhau để bạn thấy kết nối rõ ràng hơn. (*ptr).kg
⟹ (*&audi).kg
⟹ audi.kg
. Ở đây lần đầu tiên tôi sử dụng thực tế ptr
là một "địa chỉ audi
" tức là &audi
và thực tế là các toán tử "tham chiếu" &
và "dereference" *
hủy bỏ nhau.