Như với tất cả mọi thứ điều đó có vẻ đáng sợ hơn lúc đầu, đó là cách tốt nhất để vượt qua nỗi sợ ban đầu là đắm mình vào sự khó chịu của số chưa biết! Đó là vào những thời điểm mà chúng ta học được nhiều nhất.
Thật không may, có những hạn chế. Trong khi bạn vẫn đang học cách sử dụng một hàm, bạn không nên giả định vai trò của một giáo viên, ví dụ. Tôi thường đọc câu trả lời từ những người dường như không biết cách sử dụng realloc
(tức là câu trả lời hiện được chấp nhận!) nói cho người khác biết cách sử dụng không chính xác, đôi khi dưới vỏ bọc rằng họ đã xử lý lỗi bị bỏ qua, mặc dù đây là một cạm bẫy phổ biến mà cần phải đề cập đến. Here's an answer explaining how to use realloc
correctly. Lưu ý rằng câu trả lời đang lưu trữ giá trị trả lại vào một biến số khác nhau để thực hiện kiểm tra lỗi.
Mỗi khi bạn gọi một hàm và mỗi khi bạn sử dụng một mảng, bạn đang sử dụng một con trỏ. Các chuyển đổi đang diễn ra hoàn toàn, mà nếu bất cứ điều gì thậm chí còn đáng sợ hơn, vì đó là những thứ chúng ta không thấy thường gây ra nhiều vấn đề nhất. Ví dụ, rò rỉ bộ nhớ ...
Các toán tử mảng là toán tử con trỏ. array[x]
thực sự là phím tắt cho *(array + x)
, có thể được chia nhỏ thành: *
và (array + x)
. Rất có thể là *
là điều khiến bạn bối rối. Chúng tôi cũng có thể loại bỏ việc bổ sung từ các vấn đề bằng cách giả sử x
là 0
, do đó, trở thành array[0]
*array
vì thêm 0
sẽ không thay đổi giá trị ...
... và do đó chúng ta có thể thấy rằng *array
tương đương với array[0]
. Bạn có thể sử dụng nơi bạn muốn sử dụng và ngược lại. Các toán tử mảng là toán tử con trỏ.
malloc
, realloc
và bạn bè không khái niệm về con trỏ bạn đã sử dụng tất cả cùng; họ chỉ đơn thuần là sử dụng điều này để triển khai một số tính năng khác, đây là một dạng thời lượng lưu trữ khác, phù hợp nhất khi bạn muốn thay đổi mạnh mẽ, năng động trong kích thước.
Đó là một sự xấu hổ rằng hiện chấp nhận câu trả lời cũng đi ngược lại các hạt some other very well-founded advice on StackOverflow, và cùng một lúc, bỏ lỡ một cơ hội để giới thiệu một tính năng ít được biết đến mà tỏa sáng cho chính xác usecase này: Các thành viên mảng linh hoạt! Đó thực sự là một khá chia câu trả lời ... :(
Khi bạn xác định struct
của bạn, khai báo mảng của bạn vào cuối của cấu trúc, mà không cần bất kỳ giới hạn trên Ví dụ:.
struct int_list {
size_t count;
int value[];
};
Điều này sẽ cho phép bạn kết hợp mảng lại int
vào việc phân bổ giống như count
của bạn, và sau khi họ bị ràng buộc như thế này có thể rất tiện dụng!
sizeof (struct int_list)
sẽ hoạt động như thể value
có kích thước bằng 0, vì vậy nó sẽ cho bạn biết kích thước của cấu trúc với danh sách trống. Bạn vẫn cần phải thêm kích thước được chuyển đến realloc
để chỉ định kích thước danh sách của bạn.
Một mẹo hữu ích khác là hãy nhớ rằng realloc(NULL, x)
tương đương với malloc(x)
và chúng tôi có thể sử dụng điều này để đơn giản hóa mã của chúng tôi. Ví dụ:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->count = y;
return 0;
}
struct int_list *array = NULL;
Lý do tôi đã chọn để sử dụng struct int_list **
như là đối số đầu tiên có thể không có vẻ ngay lập tức rõ ràng, nhưng nếu bạn suy nghĩ về đối số thứ hai, bất kỳ thay đổi nào value
từ bên trong push_back
sẽ không được hiển thị cho chức năng mà chúng tôi đang gọi từ, phải không? Cũng vậy với đối số đầu tiên, và chúng ta cần để có thể sửa đổi array
của chúng tôi, không chỉ đây nhưng có thể là ở khắp mọi chức năng khác/s chúng tôi vượt qua nó để ...
array
bắt đầu giảm giá chỉ không có gì; nó là một danh sách trống. Khởi tạo cũng giống như thêm vào nó. Ví dụ:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
Đây là vấn đề (rất, rất nhỏ) trong C, nhưng làm cách nào bạn bỏ lỡ tất cả các giải pháp C++ và C# cho điều này? –
"Nếu con trỏ là giải pháp duy nhất, làm thế nào tôi có thể theo dõi chúng để tránh rò rỉ?" Chăm sóc, chú ý và valgrind. Đây là lý do tại sao mọi người rất sợ nếu C ở nơi đầu tiên. –
Bạn không thể sử dụng C một cách hiệu quả mà không cần sử dụng con trỏ. Đừng sợ. – qrdl