- Kết quả trả về của hàm là ký tự được ấn.
Chúng ta đã làm quen với kiểu con trỏ trong “Bài 6” Con trỏ là biến chứa địa chỉ chứ không phải chứa giá trị số liệu.
2.2. Cấp phát và giải phóng bộ nhớ động (các hàm thuộc stdlib.h và alloc.h)
Để cấp phát bộ nhớ động ta sử dụng các hàm trong thư viện stdlib.h hoặc alloc.h. Gồm:
Cấp phát bộ nhớ động bằng hàm malloc()
Cú pháp
void *malloc(size_t size)
Chức năng: Hàm malloc cấp phát một vùng nhớ có kích thước là size. Trong đó:
size là một giá trị kiểu size_t (là một kiểu dữ liệu định sẵn trong thư viện stdlib.h, ta có thể khai báo kiểu unsigned cũng được).
Hàm này trả về con trỏ kiểu void chứa địa chỉ ô nhớ đầu của vùng nhớ được cấp phát. Nếu không đủ vùng nhớ để cấp phát nó sẽ trả về giá trị NULL, vì vậy ta phải kiểm tra giá trị trả về khi sử dụng hàm malloc.
Phân tích một số trường hợp minh họa
# include <stdlib.h> # include <conio.h>
void main () /* Ham chinh */ { void *v; clrscr(); if ((v=malloc(100))==NULL) { printf("Khong du bo nho"); exit(1); }
printf("Bo nho da duoc cap phat"); getch();
}
Nếu muốn cấp phát vùng nhớ để lưu một loại dữ liệu xác định nào đó thì ta có thể ép kiểu đối với con trỏ trả về của hàm malloc:
Ví dụ 2 int *num;
num=(int*)malloc(50*sizeof(int));
dòng lệnh trên yêu cầu cấp phát vùng nhớ để lưu giữ 50 giá trị kiểu nguyên. Giá trị trả về là con trỏ kiểu nguyên lưu địa chỉ đầu của vùng nhớ được cấp phát.
Chú ý: Toán tử sizeof cho ta kích cỡ tính theo byte của một kiểu dữ liệu (int, float, hay
các kiểu được định nghĩa trong chương trình bằng typedef, enum…) cũng như một đối tượng dữ liệu (biến, mảng,cấu trúc). Nó được viết như sau:
sizeof(kiểu dữ liệu) sizeof(đối tượng dữ liệu)
Ví dụ: Như trên sizeof(int) cho ta kích cỡ tính theo byte của kiểu int (bằng 2 byte ).
Cấp phát bộ nhớ động bằng hàm calloc()
Cú pháp
(datatype *) calloc(n, sizeof(object));
Chức năng của hàm là: cấp phát bộ nhớ động cho các kiểu dữ liệu (có thể là những kiểu dữ liệu không phải kiểu cơ sở)
Trong đó:
(datatype *) là kiểu con trỏ trỏ tới kiểu dữ liệu datatype.
n là số lượng object thuộc kiểu datatype mà ta cần cấp phát bộ nhớ.
Kiểu datatype có thể là những kiểu dữ liệu mới do người lập trình sáng tạo ra. Phân tích trường hợp minh họa
struct sv {
unsigned int tuoi; unsigned int diem;
} /* Khai báo cấu trúc */ struct sv *p_sv; /* Khai báo con trỏ sv*/
Cấp phát bộ nhớ cho 10 người:
calloc(10, sizeof(struct sv));
Cấp phát bộ nhớ động bằng hàm relloc()
Cú pháp
(datatype *) realloc(buf _p, newsize);
Phân tích
Chức năng: Hàm cấp phát lại bộ nhớ Trong đó:
buf_p là con trỏ đang trỏ đến vùng ô nhớ đã được cấp phát từ trước. newsize là kích thước mới cần cấp phát, có thể to hoặc nhỏ hơn. Giải phóng bộ nhớ động bằng hàm free()
Cú pháp
void free( void *prt)
Chức năng:
Hàm free giải phóng vùng nhớ được trỏ đến bởi con trỏ ptr. Nếu ptr = NULL thì free không làm gì cả.
Chương trình ví dụ
Viết chương trình nhập các số nguyên từ bàn phím. Xuất các số ra màn hình ( không sử dụng mảng):
# include "stdio.h" # include "stdlib.h" # include "conio.h"
void main () /* Ham chinh */ {
int *num,i,j; clrscr();
printf("Nhap so phan tu"); scanf("%d",&i);
/* Cấp phát bộ nhớ bằng hàm malloc*/ num=(int*)malloc(i*sizeof(int)); for (j=0;j<i;j++)
printf("\n Ký tự thứ %d",j); scanf(" %d",(num+j)); } for (j=0;j<i;j++) printf("%c \n",*(num+j)); getch(); /*Giải phóng bộ nhớ*/ free(num); } Ví dụ sử dụng hàm malloc
Ví dụ: Dùng hàm malloc cấp phát bộ nhớ cho một chuỗi ký tự
#include <stdio.h> #include <string.h> #include <alloc.h> #include <process.h> int main(void) { char *str; /*Cấp phát bộ nhớ cho chuỗi */
if ((str = (char *) malloc(10)) == NULL) {
printf("Không đủ bộ nhớ để cấp phát \n");
exit(1); /* Kết thúc chương trình, nếu tràn bộ nhớ*/ }
/* Sao chép "Hello" vào chuỗi */ strcpy(str, "Hello"); /* Hiển thị chuỗi */ printf("Chuỗi ký tự là: %s\n", str); /* Giải phóng bộ nhớ */ free(str); return 0; } Ví dụ sử dụng hàm calloc
Ví dụ: Dùng hàm calloc cấp phát bộ nhớ cho một chuỗi ký tự
#include <stdio.h> #include <alloc.h>
#include <string.h> int main(void) {
char *str = NULL;
/* Cấp phát bộ nhớ cho chuỗi */ str = (char *) calloc(10, sizeof(char)); /* Sao chép "Hello" vào chuỗi */ strcpy(str, "Hello"); /* Hiển thị chuỗi */ printf("Chuỗi ký tự là %s\n", str); /* Giải phóng bộ nhớ */ free(str); return 0; } Ví dụ sử dụng hàm realloc
Ví dụ: Dùng hàm realloc cấp phát lại bộ nhớ cho một chuỗi ký tự
#include <stdio.h> #include <alloc.h> #include <string.h> int main(void) { char *str; /* Cấp phát bộ nhớ cho chuỗi */ str = (char *) malloc(10); /*Sao chép "Hello" vào chuỗi */ strcpy(str, "Hello");
printf("Chuỗi ký tự là %s\n Địa chỉ là %p\n", str, str); str = (char *) realloc(str, 20);
printf("Chuỗi ký tự là %s\n Địa chỉ mới là %p\n", str, str); /*Giải phóng bộ nhớ */
free(str); return 0; }