DÁNH SÁCH BÀI VIẾT Lập trình là gì? Một số khái niệm trong lập trình Cài đặt IDE Dev C++ – Môi trường lập trình C/C++ Làm quen với ngôn ngữ C – Chương trình Hello World Những cú pháp cơ bản Các kiểu dữ liệu Biến và Toán tử Vòng lặp for, while và do…while Câu lệnh điều kiện if else Cấu Trúc Rẽ Nhánh Switch … Case Từ khóa break và continue Mảng Hàm Tham biến và Tham trị Chuỗi ký tự Một số hàm xử lý chuỗi Con trỏ Đọc ghi file Struct – Dữ liệu kiểu cấc trúc
Bài viết này sẽ giúp các bạn hiểu thế nào là con trỏ, các khái niệm cơ bản liên quan đến con trỏ cũng như cách sử dụng con trỏ trong C. Con trỏ là phần kiến thức khá rộng, do đó bài viết này sẽ chỉ hướng dẫn về con trỏ cơ bản. Chúng ta cùng bắt đầu nhé.
Con trỏ là gì?
Một con trỏ là một biến mà trong đó giá trị của nó là địa chỉ. Ví dụ như địa chỉ của vùng nhớ. Giống như các biến và hằng số, bạn phải khai báo con trỏ trước khi bạn có thể sử dụng nó để lưu trữ bất kì địa chỉ của biến nào.
Khai báo con trỏ
Khai báo con trỏ ta xử dụng cú pháp sau:
kieu_du_lieu *ten_bien;
Ở đây, kieu_du_lieu là kiểu dữ liệu cơ bản con trỏ, nó là kiểu hợp lệ trong ngôn ngữ C và ten_bien là tên giá trị của con trỏ. Phần ký tự * hiểu là để khai báo co trỏ.
Ví dụ:
char *a
Đây là 1 khai báo con trỏ hợp lệ.
Cấp phát bộ nhớ cho con trỏ
Để cấp phát vùng nhớ động cho biến trong ngôn ngữ C, bạn có thể sử dụng hàm malloc()
hoặc hàm calloc()
. Sử dụng hàm free()
để giải phóng bộ nhớ đã cấp phát khi không cần sử dụng, sử dụng realloc()
để thay đổi (phân bổ lại) kích thước bộ nhớ đã cấp phát trong khi chạy chương trình.
Sử dụng hàm malloc()
Từ malloc là đại diện cho cụm từ memory allocation (dịch: cấp phát bộ nhớ).
Hàm malloc()
thực hiện cấp phát bộ nhớ bằng cách chỉ định số byte cần cấp phát. Hàm này trả về con trỏ kiểu void
cho phép chúng ta có thể ép kiểu về bất cứ kiểu dữ liệu nào.
Cú pháp của hàm malloc()
:
ptr = (castType*) malloc(size);
Ví dụ:
ptr = (int*) malloc(100 * sizeof(int));
Ví dụ trên thực hiện cấp phát cho việc lưu trữ 100 số nguyên. Giả sử sizeof int
là 4, khi đó lệnh dưới đây thực hiện cấp phát 400 bytes. Khi đó, con trỏ ptr
sẽ có giá trị là địa chỉ của byte dữ liệu đầu tiên trong khối bộ nhớ vừa cấp phát.
Trong trường hợp không thể cấp phát bộ nhớ, nó sẽ trả về một con trỏ NULL
.
Sử dụng hàm calloc()
Hàm malloc()
khi cấp phát bộ nhớ thì vùng nhớ cấp phát đó không được khởi tạo giá trị ban đầu. Trong khi đó, hàm calloc()
thực hiện cấp phát bộ nhớ và khởi tạo tất cả các ô nhớ có giá trị bằng 0.
Hàm calloc()
nhận vào 2 tham số là số ô nhớ muốn khởi tạo và kích thước của 1 ô nhớ.
Cú pháp của hàm calloc():
ptr = (castType*)calloc(n, size);
Ví dụ:
ptr = (int*) calloc(100, sizeof(int));
Trong ví dụ trên, hàm calloc()
thực hiện cấp phát 100 ô nhớ liên tiếp và mỗi ô nhớ có kích thước là số byte của kiểu int
. Hàm này cũng trả về con trỏ chứa giá trị là địa chỉ của byte đầu tiên trong khối bộ nhớ vừa cấp phát.
Sử dụng hàm realloc()
Hàm realloc() cố gắng để phục hồi khối bộ nhớ được trỏ tới bởi con trỏ ptr mà đã được cấp phát trước đó với một lời gọi tới malloc hoặc calloc.
cú pháp:
ptr = realloc(ptr, size)
với ptr ở đây là con trỏ tới khối bộ nhớ đã được cấp phát trước đó với malloc, calloc hoặc realloc để được tái cấp phát. Nếu giá trị là NULL, thì một khối mới được cấp phát và một con trỏ tới nó được trả về bởi hàm này
Ví dụ:
//cap phat bo nho
str = (char *) malloc(25);
/* tai cap phat lai bo nho */
str = (char *) realloc(str, 25);
Sử dụng hàm free()
Việc cấp phát bộ nhớ động trong C dù sử dụng malloc()
hay calloc()
thì chúng cũng đều không thể tự giải phóng bộ nhớ. Bạn cần sử dụng hàm free()
để giải phóng vùng nhớ.
Cú pháp:
free(ptr); // ptr là con trỏ
Lệnh này sẽ giải phóng vùng nhớ mà con trỏ ptr
đã được cấp phát. Giải phóng ở đây có nghĩa là trả lại vùng nhớ đó cho hệ điều hành và hệ điều hành có thể sử dụng vùng nhớ đó vào việc khác nếu cần.
Cách sử dụng con trỏ
int *a;
Trong khai báo này lúc này biến a sẽ là con trỏ tức là địa chỉ của ô nhớ.
Bằng cách sử dụng toán tử *, lúc này chúng ta có thể in giá trị của biến con trỏ a bằng cách gọi *a.
Ví dụ:
#include<stdio.h>
int main()
{
int b=5;
int *a;
a = &b;
printf("Dia chi con tro: %x\n Gia tri: %d ", a, *a);
}
Output:
Sử dụng con trỏ thay thế cho mảng
Bản chất của mảng là tập hợp các phần tử có cùng kiểu và nằm liền kề nhau trong các ô nhớ.
Như vậy, nếu như đã biết được địa chỉ ô nhớ thứ nhất thì chúng ta cũng có thể biết được địa chỉ các ô nhớ tiếp theo.
Ví dụ minh họa:
#include<stdio.h>
#include <malloc.h>
int main()
{
int *a;
a = (int*)malloc(5*4); //Cap phat bo nho gom 5 phan tu voi moi phan tu la 4 byte
for(int i = 0;i<5;i++)
{
printf("Nhap a[%d] = ", i);
scanf("%d", a+i);
}
printf("\n\n====\n");
for(int i = 0;i<5;i++)
printf("%d ", *(a+i));
}
Output:
Qua bài viết và một vài ví dụ trên đây hy vọng có thể giúp các bạn hiểu rõ hơn về con trỏ trong C.