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  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 = 84;
 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

con trỏ trong c

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ỏ 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ỏ 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ỏ 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.

Xem giáo trình môn lập trình c

Trả lời