Con trỏ trong c (Bài 8)
Con trỏ trong c là gì? Con trỏ là biến được dùng để chứa địa chỉ vùng nhớ của một biến khác. Nếu một biến chứa địa chỉ của biến khác, thì biến đầu tiên được gọi là con trỏ.
Con trỏ hỗ trợ một phương pháp gián tiếp giúp truy cập dữ liệu của biến mà con trỏ đó đang trỏ đến.
Con trỏ có thể trỏ đến các biến của các kiểu dữ liệu như int, long, float, double, char hoặc dữ liệu kiểu cấu trúc.
Tại sao phải sử dụng con trỏ?
Có thể liệt kê một số tình huống mà con trỏ có thể được sử dụng như: xây dựng hàm trả về nhiều hơn một giá trị; thao tác trên mảng được dễ dàng hơn bằng cách di chuyển con trỏ thay vì di chuyển vị trí của các phần tử.
Con trỏ trong c – Khai báo biến con trỏ
Kiểu_Dữ_Liệu *Tên_Con_Trỏ;
Hai toán tử sử dụng với con trỏ trong c làToán tử & và toán tử *
Toán tử & được sử dụng để trả về địa chỉ vùng nhớ của biến
Tên_Biến = &Tên_Con_Trỏ;
Toán tử * được sử dụng để trả về giá trị chứa trong vùng nhớ mà con trỏ đang trỏ đến.
Tên_Biến = *Tên_Con_Trỏ;
Ví dụ khai báo con trỏ trong c
#include<stdio.h>
main() {
int x;
int *px;
x = 7;
px = &x;
printf("%d", *px);
}
Kết quả hiển thị trên màn hình là 7. Độc giả quan sát hình bên dưới để hiểu rõ hơn
Giả sử biến x có địa chỉ vùng nhớ là 0240FF8C và nội dung chứa bên trong vùng nhớ là 7 (x = 7)
Khi chúng ta thực hiện xử lý px = &x; có nghĩa là gán biến con trỏ px cho vùng nhớ 0240FF8C.
Muốn truy cập nội dung bên trong vùng nhớ này, chúng ta sử dụng *px và hiển thị kết quả bằng lệnh printf: printf(“%d”, *px);
Con trỏ trong c – Con trỏ với mảng
Như bạn đọc đã biết, chúng ta truy cập phần tử của mảng thông qua chỉ số theo cú pháp Tên_Mảng[Chỉ_Số] và tham khảo địa chỉ của mảng theo cú pháp &Tên_Mảng[i]
Đối với con trỏ cú pháp Tên_Mảng[Chỉ_Số] sẽ là *(Tên_Mảng + Chỉ_Số), cú pháp &Tên_Mảng[i] sẽ là Tên_Mảng + Chỉ_Số
Ví dụ khai báo mảng
int a[] = {3, 2, 9, 100, 7};
Truy cập phần tử thứ 3 của mảng
Mảng | Con trỏ |
int x = a[2]; | int x = *(a+2); |
Tham khảo địa chỉ mảng
Mảng | Con trỏ |
scanf(“%d”, &a[2]); | scanf(“%d”, a+2); |
Như vậy khi làm việc với mảng, chúng ta có thể sử dụng một trong hai cách như đã trình bày ở trên.
Con trỏ trong c – Con trỏ với chuỗi
Quan sát đoạn chương trình sau
#include<stdio.h>
main() {
char *welcome = "Chao ban ";
char yourname[50];
printf("Vui long nhap ten ban: "); //Thông báo
scanf("%s", &yourname); //Nhập tên
printf("%s%s", welcome, yourname); //Hiển thị
}
Kết quả
Vui long nhap ten ban: Dang
Chao ban Dang
Giải thích chương trình
welcome là biến con trỏ được khai báo và khởi tạo bằng câu lệnh char *welcome = “Chao ban” thay vì sử dụng chuỗi char welcome[10] = “Chao ban”.
Cả hai cách đều cho cùng kết quả, điểm khác biệt ở đây khi khai báo chuỗi sử dụng mảng chúng ta phải chỉ định số ký tự còn đối với con trỏ thì không.
Quan sát câu lệnh char yourname[50]; và câu lệnh char *yourname;
Con trỏ trong c – Con trỏ với hàm
Tạo hàm hoán vị 2 số nguyên: Trường hợp không sử dụng con trỏ
void hoanvi1(int a, int b) {
int t; t = a; a = b; b = t;
}
Gọi hàm
int a = 1, b = 2;
hoanvi1(a, b);
printf("a = %d, b = %d", a, b);
Kết quả hiển thị là 1, 2. Điều đó có nghĩa là giá trị của a và b vẫn giữ nguyên mặc dù bên trong hàm hoanvi1 đã thực hiện thay đổi giá trị.
Trường hợp sử dụng con trỏ
void hoanvi2(int *a, int *b) {
int t;
t = *a;
*a = *b;
*b = t;
}
Gọi hàm
int a = 1, b = 2;
hoanvi2(&a, &b);
printf("a = %d, b = %d", a, b);
Kết quả hiển thị: 2, 1. Nghĩa là giá trị của a và b đã được thay đổi ngay trong bên thân hàm. Điều này có thể được giải thích như sau
Đối với hàm hoanvi1 mặc dù chúng ta thực hiện hoán đổi giá trị cho 2 tham số a, b và đương nhiên giá trị của 2 tham số này sẽ thay đổi, tuy nhiên CHỈ THAY ĐỔI BÊN TRONG HÀM, khi kết thúc hàm giá trị của 2 tham số này vẫn giữ nguyên. Vì thực chất bên trong hàm chỉ sử dụng bản sao của biến nên mọi thay đổi bên trong hàm sẽ không được ghi nhận.
Đối với hàm hoanvi2 vì chúng ta đang sử dụng con trỏ nên việc thay đổi giá trị được thực hiện trên bản gốc của biến. Vì vậy giá trị của biến khi bị thay đổi bên trong hàm sẽ được ghi nhận sau khi kết thúc hàm.
Con trỏ trong c – Tổng kết
- Con trỏ và khai báo con trỏ
- Con trỏ với mảng
- Con trỏ với chuỗi
- Con trỏ với hàm
Con trỏ trong c – Bài tập thực hành
Bài thực hành số 1: Viết chương trình kiểm tra một chuỗi có phải là palindrome. Một chuỗi được gọi là palindrome nếu sau khi đảo ngược các ký tự của nó ta vẫn nhận được chuỗi như ban đầu. Ví dụ chuỗi MADAM.
Bài thực hành số 2: Viết chương trình nhập vào một tên và đếm số ký tự là nguyên âm và phụ âm.
Bài thực hành số 3: Viết chương trình tìm phần tử có giá trị nhỏ nhất và lớn nhất trong mảng một chiều.