Kiến thức căn bản lập trình C - Quản lý bộ nhớ trong C, tham số dòng lệnh
Quản lý bộ nhớ trong C
Chương này sẽ giải thích về cách quản lý bộ nhớ động trong ngôn ngữ C. Ngôn ngữ lập trình C cung cấp vài hàm khác nhau cho việc cấp phát và quản lý bộ nhớ. Những hàm này có thể tìm thấy trong Header file là <stdlib.h>.
STT | Hàm và Miêu tả |
---|---|
1 | void *calloc(int tongkichco, int kichco); Hàm này cấp phát một mảng các phần tử có tổng kích thước là tongkichco mà kích cỡ của mỗi phần tử được tính bằng byte sẽ là kichco. |
2 | void free(void *diachi); Hàm này giải phóng một khối bộ nhớ được xác định bởi diachi. |
3 | void *malloc(int tongkichco); Hàm này cấp phát bộ nhớ động với kích thước tongkichco. |
4 | void *realloc(void *diachi, int kichco_moi); Hàm này để thay đổi kích cỡ bộ nhớ đã cấp phát thành kích cỡ mới kichco_moi. |
Cấp phát bộ nhớ động trong C
Khi bạn lập trình, bạn phải nhận thức về độ lớn của một mảng, sau đó nó là dễ dàng cho việc định nghĩa mảng. Ví dụ, bạn lưu trữ một tên của người bất kỳ nào, nó có thể lên tới tối đa 100 ký tự vì thế bạn có thể định nghĩa như sau:
char ten_mang[100];
Bây giờ hãy xem xét trường hợp bạn không có một ý tưởng nào về độ lớn của mảng bạn dự định lưu trữ, ví dụ bạn muốn lưu trữ một miêu tả chi tiết về một chủ đề. Tại đây bạn cần định nghĩa một con trỏ tới ký tự mà không định nghĩa bao nhiêu bộ nhớ được yêu cầu và sau đó dựa vào yêu cầu chúng ta sẽ cấp phát bộ nhớ như ví dụ dưới đây:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char tennhanvien[100]; char *mieuta; strcpy(tennhanvien, "Tran Minh Chinh"); /* Cap phat bo nho dong */ mieuta = (char *) malloc(200); if( mieuta == NULL ) { fprintf(stderr, "Error - khong the cap phat bo nho theo yeu cau\n"); } else { strcpy( mieuta, "Chinh la nhan vien IT co nang luc chem gio tot!!!"); } printf("Ten nhan vien la: %s\n", tennhanvien ); printf("Mieu ta: %s\n", mieuta ); printf("\n===========================\n"); printf("VietJack chuc cac ban hoc tot! \n"); }
Biên dịch và chạy chương trình C trên sẽ cho kết quả như dưới đây
Ten nhan vien la: Tran Minh Chinh
Mieu ta : Chinh la nhan vien IT co nang luc chem gio tot!!!
Chương trình như trên có thể được viết bởi sử dụng calloc(), thay cho malloc như sau:
mieuta = (char*)calloc(200, sizeof(char));
Như thế là bạn đã hoàn toàn điều khiển việc cấp phát bộ nhớ và bạn có thể truyền bất cứ giá trị kích cỡ nào trong khi cấp phát bộ nhớ, không giống như mảng có độ dài cố định không thể thay đổi được.
Thay đổi và giải phóng bộ nhớ trong C
Khi chương trình của bạn kết thúc, hệ điều hành sẽ tự động giải phóng bộ nhớ cấp phát cho chương trình, nhưng trong thực tế khi bạn không cần bộ nhớ nữa, bạn nên giải phóng bộ nhớ bằng cách sử dụng hàm free().
Một cách khác, bạn có thể tăng hoặc giảm cỡ của khối bộ nhớ đã cấp phát bằng cách gọi hàm realloc(). Hãy kiểm tra chương trình trên lại một lần và sử dụng hàm realloc() và free():
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char tennhanvien[100]; char *mieuta; strcpy(tennhanvien, "Tran Minh Chinh"); /* Cap phat bo nho dong */ mieuta = (char *) malloc(100); if( mieuta == NULL ) { fprintf(stderr, "Error - khong the cap phat bo nho theo yeu cau\n"); } else { strcpy( mieuta, "Chinh la nhan vien IT co nang luc chem gio tot!!!"); } /* Gia su ban muon luu tru mot mieuta nho hon */ mieuta = (char*)calloc(50, sizeof(char)); if( mieuta == NULL ) { fprintf(stderr, "Error - khong the cap phat bo nho theo yeu cau\n"); } else { strcat( mieuta, "Anh ta rat gioi!!!"); } printf("Ten nhan vien: %s\n", tennhanvien ); printf("Mieu ta: %s\n", mieuta ); /* giai phong bo nho voi ham free() */ free(mieuta); printf("\n===========================\n"); printf("VietJack chuc cac ban hoc tot! \n"); }
Biên dịch và chạy chương trình C trên sẽ cho kết quả như dưới đây
Ten nhan vien : Tran Minh Chinh
Mieu taL Anh ta rat gioi!!!
Bạn có thể thử ví dụ trên mà không sử dụng việc cấp phát thêm và hàm strcat() sẽ thông báo lỗi do không đủ bộ nhớ cấp phát.
Tham số dòng lệnh trong C
Chương này chỉ thực sự có ý nghĩa với bạn nếu bạn đang sử dụng command promt để biên dịch chương trình. Nó là có thể để truyền các giá trị từ dòng lệnh – command line cho chương trình C khi nó được thực hiện. Những giá trị này được gọi là Tham số dòng lệnh - command line argument và nhiều khi rất quan trọng cho chương trình của bạn khi bạn điều khiển chương trình của bạn bên ngoài thay vì mã hóa thô những giá trị bên trong đoạn code.
Các tham số dòng lệnh được xử lý bởi sử dụng các tham số hàm main(), với argc hướng đến số lượng tham số bạn truyền và argv[] là mảng con trỏ hướng đến bất kì tham số nào cung cấp cho chương trình đó. Dưới đây là ví dụ kiểm tra nếu có bất kỳ tham số được cung cấp từ dòng lệnh và thực hiện các hành động tương ứng:
#include <stdio.h> int main( int argc, char *argv[] ) { if( argc == 2 ) { printf("Tham so duoc cung cap la: %s\n", argv[1]); } else if( argc > 2 ) { printf("Qua nhieu tham so duoc cung cap.\n"); } else { printf("Ban nen cung cap mot tham so.\n"); } }
Khi đoạn code trên được biên dịch và thực thi với 1 tham số, nó sẽ in ra kết quả sau:
$./a.out thamso1 Tham so duoc cung cap la: thamso1
Khi bạn truyền 2 tham số cho đoạn code trên nó sẽ in ra kết quả sau đây:
$./a.out thamso1 thamso2 Qua nhieu tham so duoc cung cap.
Khi đoạn code trên được thực hiện và thực thi với không có tham số nào được truyền vào, nó sẽ in ra kết quả dưới đây:
$./a.out Ban nen cung cap mot tham so.
Chú ý rằng argv[0] giữ giá trị tên của chính chương trình và argv[1] là một con trỏ đến tham số dòng lệnh đầu tiên đã cung cấp, argv[n] là tham số cuối. Nếu không có tham số nào được cung cấp, argc sẽ là 1, nếu bạn truyền 1 tham số thì sau đó argc có giá trị 2.
Bạn truyền tất cả tham số dòng lệnh riêng rẽ nhau bởi khoảng trắng, những nếu các tham số tự nó có một khoảng trắng thì bạn có thể truyền các tham số này bởi đặt chúng trong dấu trích dẫn kép ("") hoặc trích dẫn đơn (''). Bây giờ chúng ta viết lại chương trình trên khi bạn in ra tên chương trình và truyền các tham số dòng lệnh đặt bên trong dấu trích dẫn kép ("").
#include <stdio.h> int main( int argc, char *argv[] ) { printf("Ten chuong trinh la: %s\n", argv[0]); if( argc == 2 ) { printf("Tham so duoc cung cap la: %s\n", argv[1]); } else if( argc > 2 ) { printf("Qua nhieu tham so duoc cung cap.\n"); } else { printf("Ban nen cung cap mot tham so.\n"); } }
Khi đoạn code trên được biên dịch và thực hiện với một tham số đơn riêng rẽ bởi dấu cách bên trong dấu trích dẫn kép, kết quả sau đây được in ra:
$./a.out "thamso1 thamso2" Ten chuong trinh la: ./a.out Tham so duoc cung cap la: thamso1 thamso2
Nhận xét
Đăng nhận xét