Con trỏ void (Void pointers)

Khóa học lập trình C++ căn bản

5.0 (4 đánh giá)
Tạo bởi Kteam Cập nhật lần cuối 12:04 28-08-2020 44.355 lượt xem 0 bình luận
Tác giả/Dịch giả: Kteam
Học nhanh

Danh sách bài học

Con trỏ void (Void pointers)

Dẫn nhập

Ở bài học trước, bạn đã được giới thiệu về BIẾN THAM CHIẾU (Reference variables) trong C++.

Hôm nay, chúng ta sẽ tiếp tục tìm hiểu về những kiến thức liên quan đến con trỏ trong C++, cụ thể là Con trỏ void (Void pointers).


Nội dung

Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về:

Trong bài ta sẽ cùng tìm hiểu các vấn đề:

  • Con trỏ void (void pointer)
  • Ứng dụng con trỏ void
  • Hạn chế sử dụng con trỏ void

Con trỏ void (void pointer)

Bạn nên luôn luôn ghi nhớ rằng một con trỏ truyền tải hai thông tin:

  • Kiểu dữ liệu trỏ đến (int, double, ...) quy định cách truy xuất dữ liệu của vùng nhớ.
  • Địa chỉ của vùng nhớ mà nó trỏ tới quy định cụ thể nơi bạn có thể truy xuất dữ liệu.

Kiểu dữ liệu đang được trỏ đến là kiểu của con trỏ (int *, double *, ...), trong khi địa chỉ của dữ liệu là giá trị thực tế chứa trong biến con trỏ.

Vì vậy, một con trỏ void (void *) là một con trỏ không chỉ định thông tin kiểu dữ liệu. Nó cho bạn biết dữ liệu được lưu ở đâu, nhưng nó không cho bạn biết cách truy xuất dữ liệu đó.

Con trỏ void còn được gọi là con trỏ tổng quát, là một kiểu con trỏ đặc biệt có thể trỏ đến các đối tượng của bất kỳ kiểu dữ liệu nào!

Con trỏ void được khai báo giống như một con trỏ bình thường, sử dụng từ khóa void làm kiểu con trỏ:

void *ptr; // ptr là con trỏ void

Con trỏ void có thể trỏ đến các đối tượng của bất kỳ kiểu dữ liệu nào:

int n;
float f;
double d;

void *ptr;
ptr = &n; // ok
ptr = &f; // ok
ptr = &d; // ok

Tuy nhiên, con trỏ void không xác định được kiểu dữ liệu của vùng nhớ mà nó trỏ tới, chúng ta không thể truy xuất trực tiếp nội dung thông qua toán tử dereference (*) được. Vì vậy, con trỏ kiểu void cần phải được ép kiểu một cách rõ ràng sang con trỏ có kiểu dữ liệu khác trước khi sử dụng toán tử dereference (*).

int value = 10;
void *voidPtr = &value;

// cout << *voidPtr << endl; // lỗi, không thể dereference con trỏ void

int *intPtr = static_cast<int*>(voidPtr); // ép kiểu thành con trỏ int
cout << *intPtr << endl; // ok

Trong đoạn code trên, voidPtr intPtr đều trỏ vào địa chỉ của biến value, nhưng chúng ta chỉ có thể sử dụng toán tử dereference (*) lên con trỏ intPtr chứ không thể sử dụng cho con trỏ voidPtr, vì trình biên dịch không thể biết con trỏ voidPtr trỏ đến kiểu dữ liệu gì.


Ứng dụng con trỏ void

Nếu một con trỏ void không xác định được kiểu dữ liệu của vùng nhớ mà nó trỏ tới, làm thế nào để chúng ta biết kiểu dữ liệu mà nó trỏ tới là gì (int, double, …).

Thông thường, để sử dụng được con trỏ void, bạn phải lấy thông tin về kiểu con trỏ theo cách khác (sử dụng thêm tham số hoặc biến cho biết kiểu con trỏ), sau đó ép kiểu con trỏ đó đến một kiểu cụ thể (int, double, …) và sau đó sử dụng nó như bình thường.

#include <iostream>
using namespace std;

enum Type
{
	INT,
	DOUBLE
};

void printValueOfPointer(void *ptr, Type type)
{
	switch (type)
	{
	case INT:
		cout << *(static_cast<int*>(ptr)) << '\n'; // ép con trỏ void thành con trỏ int
		break;
	case DOUBLE:
		cout << *(static_cast<double*>(ptr)) << '\n'; // ép con trỏ void thành con trỏ double
		break;
	}
}

int main()
{
	int nValue = 10;
	double dValue = 6.9;

	printValueOfPointer(&nValue, INT);
	printValueOfPointer(&dValue, DOUBLE);

	system("pause");
	return 0;
}

Con trỏ void (Void pointers)

Đoạn code trên hiển thị thông tin của con trỏ nValue dValue. Thông thường, chúng ta sẽ phải viết 2 hàm hiển thị cho 2 loại con trỏ này. Tuy nhiên, chúng ta có thể sử dụng tham số kiểu void*.

Khi vào hàm printValueOfPointer(), dựa vào biến type để ép từ kiểu void* về kiểu dữ liệu tương ứng. Điều này làm giảm thiểu việc viết nhiều function cùng chức năng nhưng khác kiểu dữ liệu đầu vào.


Hạn chế sử dụng con trỏ void

Thông thường, bạn nên tránh sử dụng con trỏ void trừ khi thật cần thiết. Vì chúng cho phép bạn tránh kiểm tra kiểu, điều này cho phép bạn vô tình làm những việc không có ý nghĩa, và trình biên dịch sẽ không thông báo lỗi.

Mặc dù hàm printValueOfPointer() là một cách ngắn gọn để xây dựng một hàm duy nhất xử lý nhiều kiểu dữ liệu. Tuy nhiên, C++ đã cung cấp một cách tốt hơn để làm điều tương tự thông qua nạp chồng hàm (function overloading), hoặc khuôn mẫu hàm (dunction template). Những khái niệm này sẽ được giới thiệu trong những bài học sau.


Kết luận

Qua bài học này, bạn đã nắm được Con trỏ void (Void pointers) trong C++. Lưu ý rằng bạn nên hạn chế lạm dụng nó, trừ khi không còn cách giải quyết nào khác.

Trong bài tiếp theo, mình sẽ giới thiệu cho các bạn khái niệm CON TRỎ TRỎ ĐẾN CON TRỎ (Pointers to pointers) trong C++.

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Tải xuống

Tài liệu

Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Con trỏ void (Void pointers) dưới dạng file PDF trong link bên dưới.

Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com

Đừng quên likeshare để ủng hộ Kteam và tác giả nhé!


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Nội dung bài viết

Tác giả/Dịch giả

Khóa học

Khóa học lập trình C++ căn bản

Hiện nay, C++ đã là cái tên rất quen thuộc trong ngành lập trình. Mặc dù C++ là ngôn ngữ lập trình đã ra đời khá lâu, nhưng không phải ai cũng có cơ hội để tìm hiểu về nó.

Vì vậy, Kteam đã xây dựng lên khóa học LẬP TRÌNH C++ CĂN BẢN để cung cấp một lượng kiến thức về ngôn ngữ C++ nói riêng, và các khái niệm khác trong lập trình nói chung.

Nội dung khóa học sẽ được phân tách một cách chi tiết, nhằm giúp các bạn dễ hiểu và thực hành được ngay. Serial dành cho những bạn chưa có bất kỳ kiến thức gì về lập trình, hoặc những bạn mất căn bản muốn lấy lại kiến thức nền tảng lập trình, cụ thể là C++.

Đánh giá

win1702 đã đánh giá 15:31 18-07-2024

rarl123 đã đánh giá 22:09 09-08-2023

Tap_Tap đã đánh giá 17:59 30-07-2021

DG SuperAdmin, Author, KquizAdmin, KquizAuthor đã đánh giá 19:38 01-03-2019

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
Không có video.