Ôn tập con trỏ void
Thuộc phần Lập trình hướng đối tượng trong hành trình C của Coddy. Bài học 49 trên 61.
void* là cách C nói rằng “một con trỏ đến thứ gì đó, nhưng mình không cho bạn biết đó là gì”. Nó có thể chứa địa chỉ của bất kỳ kiểu dữ liệu nào: int, float, một struct hoặc bất kỳ thứ gì khác. Nhờ vậy, đây là nền tảng để viết code tổng quát trong C.
Điều cần lưu ý là bạn không thể giải tham chiếu trực tiếp một void*. Trình biên dịch không biết cần đọc bao nhiêu byte hoặc diễn giải chúng như thế nào. Để sử dụng dữ liệu, bạn phải ép kiểu nó về đúng kiểu:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Sự linh hoạt này đi kèm với trách nhiệm. Nếu bạn ép kiểu sang kiểu sai, trình biên dịch sẽ không ngăn bạn, nhưng chương trình sẽ tạo ra dữ liệu vô nghĩa hoặc gặp sự cố. Vì vậy, các hàm tổng quát thường kết hợp void* với một dấu hiệu kiểu dữ liệu, chẳng hạn như enum hoặc cờ, để hàm biết cách diễn giải dữ liệu cho đúng.
Trong các bài học sắp tới, bạn sẽ dùng void* để xây dựng các cấu trúc chứa có thể lưu trữ mọi kiểu dữ liệu, nhờ đó tạo ra các cấu trúc dữ liệu thực sự có thể tái sử dụng.
Thử thách
DễViết một hàm có tên print_value nhận hai tham số: một con trỏ void* trỏ đến dữ liệu và một cờ kiểu int. Hàm sẽ diễn giải và in dữ liệu dựa trên cờ kiểu:
- Nếu cờ kiểu là
0, hãy ép kiểu con trỏ thànhint*rồi in giá trị số nguyên - Nếu cờ kiểu là
1, hãy ép kiểu con trỏ thànhfloat*rồi in giá trị số thực với 2 chữ số thập phân
Chương trình sẽ nhận hai đầu vào:
- Một cờ kiểu (
0cho số nguyên,1cho số thực) - Một giá trị số
Dựa trên cờ kiểu, hãy lưu giá trị vào biến có kiểu dữ liệu phù hợp, sau đó gọi print_value với con trỏ trỏ đến biến đó và cờ kiểu.
Ví dụ đầu ra khi đầu vào là 0 và 42:
42Ví dụ đầu ra khi đầu vào là 1 và 3.14:
3.14Ví dụ đầu ra khi đầu vào là 0 và -17:
-17Ví dụ đầu ra khi đầu vào là 1 và 99.5:
99.50Tự làm thử
#include <stdio.h>
// TODO: Viết hàm (function) print_value tại đây
int main() {
int type_flag;
scanf("%d", &type_flag);
if (type_flag == 0) {
int int_value;
scanf("%d", &int_value);
// TODO: Gọi print_value với con trỏ trỏ đến int_value và cờ kiểu dữ liệu
} else if (type_flag == 1) {
float float_value;
scanf("%f", &float_value);
// TODO: Gọi print_value với con trỏ trỏ đến float_value và cờ kiểu dữ liệu
}
return 0;
}Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình mô-đun
Tệp tiêu đềInclude guardTệp mã nguồnHàm staticÔn tập: Máy tính mô-đun4Tính đóng gói
Khái niệm con trỏ mờĐịnh nghĩa struct mờHàm truy xuất và hàm gánKiểm tra tính hợp lệ trong hàm gánÔn tập: Hộp bí mật7Con trỏ hàm
Khai báo con trỏ hàmGọi con trỏ hàmDùng typedef cho con trỏ hàmTruyền hàm làm đối sốÔn tập: điều phối máy tính10Bộ chứa tổng quát
Ôn tập con trỏ voidTrình bao bọc tổng quátHoán đổi tổng quátSo sánh tổng quátÔn tập: mảng tổng quát2Đối tượng và phương thức
Struct dưới dạng đối tượngCon trỏ 'Self'Tính đúng đắn của constCon trỏ và giá trịPhương thức hỗ trợÔn tập: trình quản lý Point5Dự án: Tài khoản ngân hàng đơn giản
Thiết lập dự ánTriển khai tài khoản3Vòng đời đối tượng
Mẫu hàm khởi tạoMẫu hàm hủyKhởi tạo trên ngăn xếpSao chép sâuÔn tập: lớp bao bọc chuỗi6Kế thừa bằng cách kết hợp
Nhúng structQuy tắc thành viên đầu tiênTruy cập thành viên lớp chaUpcastingÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch C online