Con trỏ trong C / C++
Trong bài viết này, codehow sẽ giới thiệu đến các bạn con trỏ trong C / C++. Đây là một kiến thức rất quan trọng trong việc học lập trình với C và C++.
Nó là một khái niệm khá khó nhằn khi mới bắt đầu học ngôn ngữ lập trình nói chúng và ngôn ngữ C / C++ nói riêng. Có một câu nói vui rằng "Lập trình C / C++ khó nhất con trỏ", khi nắm được con trỏ thì các kiến thức khác trở nên dễ dàng.
Bây giờ chúng ta bắt đầu tìm hiểu khái niệm con trỏ là gì? Cấu trúc và cách sử dụng nó như thế nào trong C / C++. Sau đó mình sẽ thực hiện một vài ví dụ sử dụng con trỏ để các bạn có thể tham khảo nhé.
Con trỏ trong C / C++ là gì?
Khi chúng ta sử dụng biến, mảng, struct để lưu trữ dữ liệu, một vùng bộ nhớ trong máy tính sẽ lưu giá trị tạm thời của dữ liệu. Khi đó chúng ta muốn truy xuất dữ liệu từ vùng nhớ này thì cần biết được vị trí hay địa chỉ của nó trong bộ nhớ.
Nói tóm lại thì con trỏ là một biến được dùng để lưu trữ địa chỉ của dữ liệu, địa chỉ này là điểm đầu của vùng chứa dữ liệu đó trong bộ nhớ máy tính.
Giá trị của con trỏ cũng có thể là một số, vậy nên chúng ta có thể thao tác với con trỏ như: cộng, trừ, nhân, chia, ... .
Cấu trúc con trỏ trong C / C++C
Để hiểu rõ hơn, các bạn hãy xem cấu trúc của con trỏ dưới đây:
type *p;
Trong đó:
- type: Là kiểu dữ liệu của con trỏ.
- p: Là tên của con trỏ.
*Lưu ý: Kiểu dữ liệu của con trỏ phải cùng kiểu dữ liệu với dữ liệu mà chúng ta muốn lưu trữ địa chỉ.
Ví dụ: Chúng ta muốn khai báo con trỏ p với kiểu int nhưu sau.
int *p;
Ngoài ra các bạn có thể viết theo một cách khác như dưới đây.
int* p; int * p;
Khai báo nhiều con trỏ trong C / C++.
Để có thể khai báo đồng thời nhiều con trỏ, ta khai bao như dưới đây:
type *p1, *p2, *p3,... ;
Trong đó:
- type là kiểu dữ liệu của các con trỏ.
- p1, p2, p3: Là tên con trỏ.
Các con trỏ được đặt cách nhau bởi dấu phẩy, như cách khai báo dưới đây.
int *p1, *p2, *p3; char *p4, *p5;
Đối với trường hợp khai báo nhiều con trỏ, ta không được khai báo theo cách dưới đây.
int* p1, p2;
Gán địa chỉ cho con trỏ.
Để lấy địa chỉ của một dữ liệu, chẳng hạn như một biến, chúng ta sẽ thêm toán tử & vào trước tên biến.
Ví dụ:
&number;
Vậy sau khi lấy địa chỉ của biến đó, ta có thể gán cho con trỏ như sau:
Chương trình C:
#include <stdio.h> int main(void) { int number = 5; int *p; p = &number; printf("Giá trị của con trỏ: %d\n", p); printf("Giá trị của con trỏ: %d\n", number); printf("\n----------------------------\n"); printf("Chương trình này được đăng tại codehow.net"); return 0; }
Kết quả:
Chương trình C++:
#include<iostream> using namespace std; int main() { int number = 5; int *p; p = &number; cout << "Giá trị của con trỏ: "<< p <<endl; cout << "Giá trị của biến number: "<< number; cout<<"\n----------------------------\n"; cout<<"Chương trình này được đăng tại codehow.net"; return 0; }
Kết quả:
Các lợi ích khi sử dụng con trỏ trong C / C++
Dưới đây là các lợi ích khi sử dụng con trỏ trong C / C++.
- Chúng ta có thể truy xuất hoặc thay đổi giá trị được lưu tại địa chỉ đó. Điều đặc biệt hơn khi sử dụng con trỏ, chúng ta có thể thay đổi hàng loạt giá trị các biến chỉ cần thông qua một hàm.
- Chúng ta có thể thay đổi toàn bộ các phần tử trong mảng.
- Có thể thay đổi giá trị của tất cả các phần tử trong struct trong C / C++. Điều này giúp chúng ta không cần phải xử lý từng phần tử trong struct nữa.
- Có thể chọn một hàm trong nhiều hàm để sử dụng.
Cách dùng con trỏ trong C / C++
Trong C / C++ hỗ trợ cho chúng ta hai toán tử đó là & và *, vậy chức năng của hai toán tử này là gì?
- *: Được dùng để lấy giá trị của một biến.
- &: Được dùng để lấy địa chỉ của một biến.
Nghe có vẻ hơi khó hiểu đúng không ạ, vậy hãy xem ví dụ dưới đây để hiểu rõ hơn nhé.
#include<iostream> using namespace std; int main() { int a = 10; int *p; p = &a; //con tro p tro den bien a cout << "Địa chỉ của biến a là: " << &a << endl; cout << "Giá trị của con trỏ p là: " << p << endl; cout << "Địa chỉ của con trỏ p là: " << &p << endl; cout << "Giá trị của biến a là: " << a << endl; cout << "Giá trị của *p là: " << *p << endl; cout<<"\n----------------------------\n"; cout<<"Chương trình này được đăng tại codehow.net"; return 0; }
Kết quả:
\
Mình xin giải thích chương trình trên như sau:
- Khi khai báo biến a, ta gán giá trị cho biến a = 10. Khi đó giá trị biến a = 10 và địa chỉ của biến a là &a.
- Khi khai báo con trỏ *p, giá trị của con trỏ p là *p và địa chỉ của nó là &p.
- Mình tiến hành gán địa chi của biến a cho con trỏ p, khi đó giá trị của con trỏ p chính là địa chỉ của biến a.
- Con trỏ p cũng có địa chỉ riêng của nó bởi vì nó cũng là một biến được khai báo ra để lưu trữ.
Nếu đến đây các bạn vẫn chưa hiểu rõ lắm, đừng lo lắng. Hãy cùng mình thực hiện thêm một vài ví dụ ở phần tiếp theo nhé.
Ví dụ sử dụng con trỏ trong C / C++
Trong phần này mình sẽ thực hiện một số chương trình sử dụng con trỏ trong C / C++. Mỗi ví dụ mình sẽ viết bằng hai ngôn ngữ khác nhau là C và C++ để các bạn có thể lựa chọn nhé.
Ví dụ 1: Hoán đổi giá trị của hai biến mà không dùng đến biến thứ ba.
Chương trình C:
#include <stdio.h> void swap(int *x,int *y) { int t; t = *x; *x = *y; *y = t; } int main(void) { int num1,num2; printf("Nhập vào số thứ nhất: "); scanf("%d", &num1); printf("Nhập vào số thứ hai: "); scanf("%d", &num2); printf("Trước khi hoán đổi:\nSố thứ nhất: %d\nSố thứ hai: %d", num1, num2); swap(&num1,&num2); printf("\nSau khi hoán đổi:\nSố thứ nhất: %d\nSố thứ hai: %d", num1, num2); printf("\n-----------------------------------\n"); printf("Chương trình này được đăng tại codehow.net"); return 0; }
Chương trình C++:
#include <iostream> using namespace std; void swap(int *x,int *y) { int t; t = *x; *x = *y; *y = t; } int main() { int num1,num2; cout<<"Nhập vào số thứ nhất: "; cin>>num1; cout<<"Nhập vào số thứ hai: "; cin>>num2; cout<<"Trước khi đổi: \n"<<"Số thứ nhất = " <<num1<<"\nSố thứ hai = "<<num2; swap(&num1,&num2); cout<<"\nSau khi đổi: \n"<<"Số thứ nhất = " <<num1<<"\nSố thứ hai = "<<num2; cout<<"\n-----------------------------------\n"; cout<<"Chương trình này được đăng tại codehow.net"; }
Kết quả:
Ví dụ 2: Tìm số lớn nhât trong ba số sử dụng con trỏ trong C / C++.
Chương trình C:
#include <stdio.h> int main(void) { int num1, num2, num3; int *p1, *p2, *p3; //Nhận giá trị input từ người dùng printf("Nhập vào số thứ nhất: "); scanf("%d", &num1); printf("Nhập vào số thứ hai: "); scanf("%d", &num2); printf("Nhập vào số thứ ba: "); scanf("%d", &num3); //gán giá trị vào các địa chỉ p1,p2,p3 p1 = &num1; p2 = &num2; p3 = &num3; //Thực hiện các điều kiện so sánh để tìm ra số lớn nhất if(*p1 > *p2) { if(*p1 > *p3) { printf("%d là số lớn nhất",*p1); } else { printf("%d là số lớn nhất",*p3); } } else { if(*p2 > *p3) { printf("%d là số lớn nhất",*p2); } else { printf("%d là số lớn nhất",*p3); } } printf("\n-----------------------------------\n"); printf("Chương trình này được đăng tại codehow.net"); return 0; }
Chương trình C++:
#include <iostream> using namespace std; int main() { int num1, num2, num3; int *p1, *p2, *p3; //Nhận giá trị input từ người dùng cout<<"Nhập vào số thứ nhất: "; cin>>num1; cout<<"Nhập vào số thứ hai: "; cin>>num2; cout<<"Nhập vào số thứ ba: "; cin>>num3; //gán giá trị vào các địa chỉ p1,p2,p3 p1 = &num1; p2 = &num2; p3 = &num3; //Thực hiện các điều kiện so sánh để tìm ra số lớn nhất if(*p1 > *p2) { if(*p1 > *p3) { cout<<*p1<<" là số lớn nhất"; } else { cout<<*p3<<" là số lớn nhất"; } } else { if(*p2 > *p3) { cout<<*p2<<" là số lớn nhất"; } else { cout<<*p3<<" là số lớn nhất"; } } cout<<"\n-----------------------------------\n"; cout<<"Chương trình này được đăng tại codehow.net"; }
Kết quả:
Lời kết
Như vậy là chúng ta đã cùng nhau tìm hiểu về con trỏ trong C / C++. Đây là một khái niệm rất trừu tượng, nhưng khi các bạn làm việc nhiều với nó thì cảm thấy rất dễ dàng. Không có cách nào để nhớ lâu hơn cách thực hành, vì vậy hãy làm bài tập thật nhiều để sử dụng nó một cách thành thạo nhé.