Hỏi về con trỏ cấp 2 trong C

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

void CapPhat(int** a, int sodong, int socot)
{
	a = (int**)calloc(sodong, sizeof(int*));
	for(int i = 0; i < sodong; i++)
	{
		a[i] = (int*)calloc(socot, sizeof(int));
	}
}
void NhapMaTran(int** a, int sodong, int socot)
{
	for(int i = 0; i < sodong * socot; i++)
	{
		printf("Nhap vao a[%d][%d]: ",i / socot, i % socot);
		scanf("%d", &a[i / socot][i % socot]);
	}
}
void XuatMaTran(int** a, int sodong, int socot)
{
	for(int i = 0; i < sodong * socot; i++)
	{
		printf("%4d", a[i / socot][i % socot]);
		if((i + 1) % socot == 0)
			printf("\n\n");
	}
}
void ThuHoi(int** a, int sodong)
{
	for(int i = 0; i < sodong; i++)
	{
		free(a[i]);
	}
	free(a);
}
int main()
{
    int **a=NULL;
    int sodong = 3, socot = 3;
	CapPhat(a, sodong, socot);
	NhapMaTran(a, sodong, socot);
	XuatMaTran(a, sodong, socot);
	if(a != NULL)
	{
		ThuHoi(a, sodong);
	}

}

Lúc e để hàm cấp phát trong main thì vẫn chạy tốt,nhưng khi đưa ra hàm riêng thì nó crash. Giúp e sửa code với ạ.

Khi bạn cấp phát 1 vùng nhớ cho con trỏ, tức là bạn cho nó trỏ tới vùng nhớ mới.
Theo cách bạn truyền, 1 con trỏ cấp 2 vào hàm cấp phát, rồi gán a = (int**)calloc(sodong, sizeof(int*));
tức là bạn thay đổi "Giá Trị " của biến a - biến con trỏ cấp 2. khi này là bạn đang dùng Truyền Tham Trị, nên khi ra khỏi hàm, giá trị của biến con trỏ a trong hàm main sẽ vẫn giữ nguyên giá trị ban đầu của nó, tức nó vẫn lưu địa chỉ lúc khởi tạo chứ chưa trỏ tới vùng nhớ nào khác ( vùng nhờ mà bạn muốn cấp phát trong hàm CapPhat).
Muốn thay đổi giá trị của con trỏ cấp 2 a trong hàm CapPhat, bạn cần dùng con trỏ cấp 3,
khi đó hàm bạn sẽ như sau:

void CapPhat(int*** a, int sodong, int socot)
{
a = (int*)calloc(sodong, sizeof(int*));
for(int i = 0; i < sodong; i++)
{
a[i] = (int)calloc(socot, sizeof(int));
}
}

Khi đó, *a = (int**)calloc(sodong, sizeof(int*)); là bạn đang thay đổi " Giá trị tại địa chỉ con trỏ cấp 3 a đang trỏ tới - giá trị của biến con trỏ a cấp 2 trong hàm main "còn con trỏ cấp 3 a vẫn trỏ trới vùng địa chỉ ô nhớ của con trỏ cấp 2, chỉ có giá trị tại địa chỉ đó thay đổi chứ địa chỉ vẫn vậy, nó chẳng trỏ đi đâu khác , như vậy ra khỏi hàm thì giá trị mà con trỏ cấp 2 trong hàm main sẽ bị thay đổi - được cấp phát.

P/s: Bạn học về con trỏ thì nên viết ra giấy hình ảnh về bản chất của con trỏ xem nó đang trỏ tới đâu, giá trị tại địa chỉ mà nó trỏ tới là cái gì. Mình hay làm vậy :v

1 Like

http://diendan.congdongcviet.com/threads/t42977::tim-hieu-ban-chat-cua-con-tro-tu-co-ban-den-nang-cao.cpp

1 Like

ý anh là thế này ạ

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

void CapPhat(int*** a, int sodong, int socot)
{
	*a = (int**)calloc(sodong, sizeof(int*));
	for(int i = 0; i < sodong; i++)
	{
		a[i] = (int*)calloc(socot, sizeof(int));
	}
}
void NhapMaTran(int** a, int sodong, int socot)
{
	for(int i = 0; i < sodong * socot; i++)
	{
		printf("Nhap vao a[%d][%d]: ",i / socot, i % socot);
		scanf("%d", &a[i / socot][i % socot]);
	}
}
void XuatMaTran(int** a, int sodong, int socot)
{
	for(int i = 0; i < sodong * socot; i++)
	{
		printf("%4d", a[i / socot][i % socot]);
		if((i + 1) % socot == 0)
			printf("\n\n");
	}
}
void ThuHoi(int** a, int sodong)
{
	for(int i = 0; i < sodong; i++)
	{
		free(a[i]);
	}
	free(a);
}
int main()
{
    int **a=NULL;
    int sodong = 3, socot = 3;
    a = (int***) malloc(sizeof(int**));
	CapPhat(a, sodong, socot);
	NhapMaTran(a, sodong, socot);
	XuatMaTran(a, sodong, socot);
	if(a != NULL)
	{
		ThuHoi(a, sodong);
	}

}

em cảm ơn ạ

Không phải vậy bạn ơi :joy:




Ở đây mình ghi ra cái cơ bản , bạn đọc thử xem k hiểu chỗ nào. Trong hình mk cấp phát cho con trỏ cấp 1 nên dùng con trỏ cấp 2 làm tham số.

1 Like

Hàm cấp phát bạn phải truyền tham chiếu vào, không phải tham trị.
Với lại, nếu giải phóng bọ nhớ mình thường làm thì không cần phải for v đâu, free cái trỏ cấp 2 là đc rồi.
^^

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?