1. Trang chủ
  2. » Luận Văn - Báo Cáo

tìm hiểu về macro giới thiệu một sôố hàm cầốp phát bộ nhớ động trong c

19 0 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Nội dung

Như ví dụ trên, chúng ta có thể truyền kiểu int,float.Phải chỉ rõ kiểu dữ liệu của tham số và giá trị trả vềMacro tạo ra các inline code, thời gian xử lí inline code ngắn hơn thời gian g

Trang 1

Mục lục:

Phầần 1: Tìm hi u vềầ Macro trong ngôn ng l p trình Cểữ ậ 2

I Macro 2

II Hàm(Function) 4

III Hàm inline (Inline function) 5

Phầần 2: Gi i thi u m t sôố hàm cầốp phát b nh đ ng trong ớệộộớ ộC 8

Trang 2

Phần 1: Tìm hiểu về Macro trong ngôn ngữ lập trình CI.Macro

Macro được dùng để chỉ những hàm được viết ở phần Preprocessor (là các

directive (chỉ thị), cung cấp chỉ lệnh tới bộ biên dịch để tiền xử lý thông tin trước khi bắt đầu biên dịch thực sự) thay vì đặt nó vào trong phần thực thi của file nguồn,mặt khác khi nói đến macro có 1 nghĩa khác nữa, ám chỉ đến tất cả những phần định nghĩa được viết trong phần Preprocessor Trong quá trình tiền xử lí (pre-processor), các macro được sử dụng trong chương trình được thay thế bởi các khối câu lệnh tương ứng Ta có thể định nghĩa macro bằng lệnh #define.

Ví dụ:

Trang 3

// C program to illustrate macros

// Print the value of macro defined

printf("The value of LIMIT" " is %d",

LIMIT); return0;}

Ta có đầu ra: Giá trị của LIMIT là 5.

Các macro giống như một đối tượng với một văn bản thay thế: Khi bộ tiền xử lý gặp lệnh này, bất kỳ sự xuất hiện nào nữa của định danh macro sẽ được thay thế bằng một đoạn văn bản mà chúng ta đã định nghĩa trước đó Thông thường thì tên định danh của macro sẽ được ghi bằng các chữ in hoa, sử dụng dấu gạch dưới để thể hiện khoảng trắng.

Ví dụ:

Trang 4

Chương trình chạy in ra: My name is: Alex

Các macro cũng có thể giống như đối tượng mà không có văn bản thay thếVí dụ:

Hàm(Function) là 1 khối lệnh thực hiện một chức năng nào đó.

Ví dụ: Hàm tìm giá trị lớn nhất của 1 số nguyên

Trang 5

Ta có kết quả đầu ra:

Ưu nhược điểm của Macro và Hàm:

Việc định nghĩa đơn giản hơn

không thể debug tìm lỗi của macro

trong thời gian thực thi Debug đơn giản, dễ bắt lỗiMacro không cần quan tâm kiểu dữ

liệu của tham số và kiểu trả về Như ví dụ trên, chúng ta có thể truyền kiểu int,float.

Phải chỉ rõ kiểu dữ liệu của tham số và giá trị trả về

Macro tạo ra các inline code, thời gian xử lí inline code ngắn hơn thời gian gọihàm

Chương trình mất thời gian dịch từ vùng nhớ hàm được lưu trữ sang vùng nhớ goi hàm.

Giả sử macro được gọi 20 lần trong chương trình, 20 dòng code sẽ được chèn vào chương trình trong quá trình tiền xử lí Điều này làm cho kích thướccủa chương trình (.EXE, DLL, LIB,…) phình to ra.

Giả sử 1 hàm được gọi 20 lần, sẽ chỉ có1 bản copy của hàm trong chương trình Kích thước chương trình nhỏ hơnsử dụng macro.

III.Hàm inline (Inline function)

Trang 6

Hàm inline là một hàm bình thường được định nghĩa bởi từ khoá inline Hàm nội tuyến (inline) là một hàm ngắn được mở rộng bởi trình biên dịch Và các đối sốcủa nó chỉ được đánh giá một lần Hàm nội tuyến là các hàm có độ dài ngắn được tự động tạo thành các hàm nội tuyến mà không cần sử dụng từ khoá nội tuyến bên trong lớp.

Cú pháp một hàm inline:

Inline return_type function_name (tham số){

//mã hàm nội tuyến}

Ví dụ:

Trang 7

Đầu ra:

Max (100, 1000): 1000Max (20, 0): 20

Sự khác nhau giữu Inline và Macro trong C++:

Trong khi macro không thể truy cập các thành viên dữ liệu của lớp.

Trong trường hợp hàm nội tuyến,

chương trình có thể dễ dàng gỡ lỗi Trong khi trong trường hợp macro, chương trình không thể dễ dàng gỡ lỗi.Trong trường hợp nội dòng, các đối số

chỉ được đánh giá một lần Trong khi trong trường hợp macro, các đối số được đánh giá mọi lúc bất cứ khinào macro được sử dụng trong chương trình.

Trong C ++, nội tuyến có thể được định nghĩa bên trong lớp hoặc bên ngoài lớp.

Trong khi macro là tất cả thời gian được xác định ở đầu chương trình.Trong C ++, bên trong lớp, các hàm có

độ dài ngắn sẽ tự động trở thành các hàm nội tuyến.

Macro được xác định cụ thể.Inline không được sử dụng rộng rãi

như macro Macro được sử dụng rộng rãi.Inline không được sử dụng trong lập

trình cạnh tranh Macro được sử dụng rất nhiều trong lập trình cạnh tranh.Hàm inline được kết thúc bằng dấu

ngoặc nhọn ở cuối

Trong khi macro không được kết thúc bằng bất kỳ ký hiệu nào, nó được kết thúc bằng một dòng mới.

Trang 8

Phần 2: Giới thiệu một số hàm cấp phát bộ nhớ động trong C

Mỗi khi tạo ra một biến nào đó, trình biên dịch sẽ đưa ra 1 địa chỉ để lưu giữbiến đó Khi chúng ta sử dụng biến có thể truy cập bằng tên biến hoặc con trỏ Việccấp phát như vậy gọi là cấp phát tĩnh Khi cấp phát tĩnh, ô nhớ đó sẽ tồn tại từ khi chương trình hoạt động tới khi chương trình kết thúc Khi phải khai báo 1 mảng màchưa rõ phải sử dụng kích thước là bao nhiêu Vậy thì nếu cấp phát tĩnh bộ nhớ chomảng đó sẽ xảy ra 2 vấn đề: Thiếu kích thước dẫn tới lưu thiếu bộ nhớ hoặc thừa kích thước dẫn tới lãng phí bộ nhớ Vậy nên chúng ta cần phải sử dụng cấp phát bộ nhớ động trong trường hợp này Cấp phát động bộ nhớ chính là việc cấp phát/giải phóng, thay đổi kích thước bộ nhớ một cách linh hoạt Giúp chúng ta điềukhiển được việc sử dụng bộ nhớ của chương trình.

Sự giống và khác nhau của việc cấp phát động và cấp phát tĩnhCấp phát bộ nhớ tĩnhCấp phát bộ nhớ động

Bộ nhớ được cấp phát trước khi chạy chương trình (trong quá trình biên dịch)

Bộ nhớ được cấp phát trong quá trình chạy chương trình.

Trang 9

Không thể cấp phát hay phân bổ lại bộ nhớ trong khi chạy chương trình

Cho phép quản lý, phân bổ hay giải phóng bộ nhớ trong khi chạy chương trình

Vùng nhớ được cấp phát và tồn tại cho

đến khi kết thúc chương trình Vùng nhớ được cấp phát và tồn tại cho đến khi kết thúc chương trìnhChương trình chạy nhanh hơn so với

cấp phát động

Chương trình chạy chậm hơn so với cấp phát tĩnh

Tốn nhiều không gian bộ nhớ hơn Tốn nhiều không gian bộ nhớ hơn

Để cấp phát vùng nhớ động cho biến con trỏ 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 feee() để 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.

I.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);

Trong ví dụ trên, hàm calloc() thực hiện cấp phát 100 ô nhớ liêntiếp và mỗi ô nhớ có kích thước là số byte của kiểu int, như vậy ở ví dụ trên thì hàm cấp phát cho con trỏ kiểu int, với kích thước là 100*4 = 400byte, vì 1 int có kích thước là 4 byte 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.Trong trường hợp không thể cấp phát bộ nhớ, nó sẽ trả về một con trỏ NULL.

Trang 10

II.Sử dụng hàm calloc()

Từ calloc đại diện cho cụm từ contiguous allocation (dịch: cấp phát liên tục).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 Vì thế nên hàm calloc sẽ cần thời gian thực thi lâu hợn malloc()

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ới n là số lượng phần tử, size là kích thước mỗi phần tử)

Hàm calloc được định nghĩa như sau: void* ICACHE_RAM_ATTR calloc(size_t count, size_t size)

Giá trị trả về là con trỏ void, tham số truyền vào là số lượng phần tử và kích thước của phần tử.

VD: #include <stdio.h>

#include <stdlib.h>

int main(){ i nint, ; int *;

printf("Nhap so phan tu: \n"); scanf("%d",& );n a = ( *)intcalloc n,(sizeof int( )); printf("Nhap %d so: \n",n); for( =0 i i n i; < ; ++ ) {

scanf("%d",&a[i]); }

printf("Cac so vua nhap la: \n");

Trang 11

printf("%d ",a i[ ]); }

return( );0}

Ta có kết quả chạy:

III.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 Nếu không giải phóng nó thì nó sẽ tồn tại cho tới khi chương trình kết thúc Điều này sẽ rất nguy hiểm nếu chương trình liên tục cấp phát các vùng nhớ mới và sẽ gây ra hiện tượng tràn bộ nhớ.

Ví dụ sử dụng hàm malloc() và free()

#include <stdio.h>

// Thư viện này cần để cấp phát bộ nhớ động

#include <stdlib.h>

intmain(){

Trang 12

// hàm malloc sẽ trả về con trỏ NULL

printf("Tong = %d",sum);

// Giải phóng vùng nhớ cho con trỏ

free(ptr);

return0;}

Trang 13

IV.Sử dụng hàm realloc()

Nếu việc cấp phát bộ nhớ động không đủ hoặc cần nhiều hơn mức đã cấp phát, bạn có thể thay đổi kích thước của bộ nhớ đã được cấp phát trước đó bằng cách sử dụng hàm realloc().

Cú pháp của realloc(): ptr = realloc(ptr, n);

Hàm này thực hiện cấp phát vùng nhớ mới cho con trỏ ptr Vùng nhớ mới đó sẽ có kích thước mới là n bytes.

Hàm này cũng trả về con trỏ chứa giá trị là địa chỉ của byte đầu tiên trong vùng nhớ mới Hàm này sẽ cố gắng mở rộng số ô nhớ ra phía sau nếu có thể để giữ nguyên giá trị của con trỏ ban đầu Trong trường hợp phải đổi sang một vùng nhớ khác, hàm realloc() cũng sẽ mang theo giá trị đã có ở vùng nhớ cũ sang vùng nhớ mới và giải phóng luôn vùng nhớ cũ (đọc thêm tài liệu số 2) Trong trường hợp không thể, nó sẽ trả về con trỏ NULL giống như malloc()calloc().

Ví dụ:

#include <stdio.h>#include <stdlib.h>

int main(){

int *ptr, i n1,n2;

printf("Nhap so luong phan tu: "); scanf("%d", &n1);

ptr=(int*)malloc(n1 *sizeof(int));

printf("Dia chi cua vung nho vua cap phat: %u",ptr);

printf("\nNhap lai so luong phan tu: "); scanf("%d", &n2);

// phân bổ lại vùng nhớ

ptr=(int*)realloc(ptr,n2 *sizeof(int));

Trang 14

printf("Dia chi cua vung nho duoc cap phat lai: %u",ptr); // giải phóng

free(ptr); return0;}

Kết quả chạy chương trình:

V.Lời kết:

Việc sử dụng phương thức calloc sẽ an toàn hơn malloc trong lập trình vì vùng nhớ cấp phát động sẽ được gán giá trị bằng 0 thay vì giá trị rác như calloc Tuy nhiên việc thêm 1 bước gán giá trị các ô nhớ bằng 0 này cũng sẽ khiến nó bị chậm hơn so với malloc do phải thực hiện thêm thao tác.

Sử dụng realloc và free một cách linh hoạt sẽ giúp các bạn điều khiển sự tăng giảm của bộ nhớ 1 cách dễ dàng

Phần 3: Bài tập lập trình

Trang 15

Bài 1: Sử dụng mảng cấp phát động để thực hiện phép nhân ma trận

#include <conio.h>#include<stdio.h>

//C?ng hai ma tr?n

void AddMatrix(int *A,int *B,int*C,int M,int N) {

for(int I=0;I<M*N;++I) C[I] = A[I] + B[I]; }

//C?p phát vùng nh? cho ma tr?n

int AllocMatrix(int **A,int M,int N) // chú ý : ** {

*A = new int [M*N]; if (*A == NULL) return 0; return 1; }

//Gi?i phóng vùng nh? void FreeMatrix(int *A) {

if (A!=NULL) delete [] A; }

Trang 16

//Nh?p các giá tr? c?a ma tr?n

void InputMatrix(int *A,int M,int N,char Symbol) {

for(int I=0;I<M;++I) for(int J=0;J<N;++J){

printf("\n %c [%d][%d] = ", Symbol,I,J);scanf("%d",&A[I*N+J]);

//Hi?n th? ma tr?n

void DisplayMatrix(int *A,int M,int N) {

for(int I=0;I<M;++I) {

for(int J=0;J<N;++J) printf("%7d",A[I*N+J]); printf("\n");

} }

void NhanMT(int *A, int *B, int *D, int hang, int cot) {for (int i = 0; i < hang; i++) {

for (int j = 0; j < cot; j++) {D[i * cot + j] = 0;

for (int k = 0; k < cot; k++) {

Trang 17

D[i * cot + j] += A[i * cot + k] * B[k * cot + j];}

// void NhanMT (int *A, int *B, int *D, int M, int N){// for (int i=0 ; i< M; i++){

int M,N;

int *A = NULL,*B = NULL,*C = NULL, *D=NULL; printf("\n Nhap so dong cua ma tran: "); scanf("%d",&M); printf("\n Nhap so cot cua ma tran: "); scanf("%d",&N);//C?p phát vùng nh? cho ma tr?n A

if (!AllocMatrix(&A,M,N)) {

printf("\n Khong con du bo nho! ");

Trang 18

return 1; }

//C?p phát vùng nh? cho ma tr?n B if (!AllocMatrix(&B,M,N)) {

printf("\n Khong con du bo nho! "); FreeMatrix(A);//Gi?i phóng vùng nh? A return 1;

}

//C?p phát vùng nh? cho ma tr?n C if (!AllocMatrix(&C,M,N))

{

printf("\n Khong con du bo nho! "); FreeMatrix(A);//Gi?i phóng vùng nh? A FreeMatrix(B);//Gi?i phóng vùng nh? B return 1;

}

if (!AllocMatrix(&D,5,5)) {

printf("\n Khong con du bo nho! "); FreeMatrix(A);//Gi?i phóng vùng nh? A FreeMatrix(B);//Gi?i phóng vùng nh? B FreeMatrix(C);//Gi?i phóng vùng nh? C return 1;

}

Trang 19

printf("\n Nhap ma tran thu 1 "); InputMatrix(A,M,N,'A'); printf("\n Nhap ma tran thu 2 "); InputMatrix(B,M,N,'B'); printf("\n Ma tran thu 1\n"); DisplayMatrix(A,M,N); printf("\n Ma tran thu 2\n"); DisplayMatrix(B,M,N); AddMatrix(A,B,C,M,N); printf("\n Tong hai ma tran\n"); DisplayMatrix(C,M,N); NhanMT(A,B,D,M,N); printf("\nTich hai ma tran\n"); DisplayMatrix(D,M,N);

FreeMatrix(A);//Gi?i phóng vùng nh? A FreeMatrix(B);//Gi?i phóng vùng nh? B FreeMatrix(C);//Gi?i phóng vùng nh? C

FreeMatrix(D);//Gi?i phóng vùng nh? C return 0;

}

Ngày đăng: 11/06/2024, 17:41

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w