2009-01-15 35 views
7

Trên thảo luận về bộ nhớ động ở đây: "Intro to C Pointers and Dynamic Memory"Mảng Variable Sized vs calloc trong C

Các trạng tác giả:

Một khối bộ nhớ như thế này hiệu quả có thể được sử dụng như một mảng linh hoạt hơn. Cách tiếp cận này thực sự phổ biến hơn trong các chương trình C trong thế giới thực. Nó cũng có thể dự đoán và linh hoạt hơn so với một "mảng kích thước biến"

Các loại khối bộ nhớ ông đang nói về là như vậy:

const int size = 5; 
int * array = calloc(size, sizeof(int)); 

và sau đó sử dụng con trỏ khác để lặp qua mảng:

int * index = array; 
for (i = 0; i < size; i++) { 
    *index = 1; // or whatever value 
    index++; 
} 

câu hỏi của tôi là như thế nào là phương pháp này tốt hơn so với một mảng tiêu chuẩn có kích thước biến như thế này ?:

int array[variable]; 

hoặc động:

char name[] = "Nick"; 

Tác giả không thực sự làm sáng tỏ vì sao tôi nên thích phương pháp cũ để sau này. Hay cụ thể hơn: Làm thế nào nó có thể dự đoán và linh hoạt hơn?

+2

có thể trùng lặp của [VS. mảng malloced variable-length-array] (http://stackoverflow.com/questions/16672322/malloced-array-vs-variable-length-array) –

Trả lời

10

Nếu bạn khai báo int array[variable] bộ nhớ sẽ được cấp phát trên ngăn xếp không tốt cho cấu trúc dữ liệu lớn, tương đối vĩnh viễn (chẳng hạn như cấu trúc bạn có thể muốn trả lại). Bạn không cần phải giải phóng bộ nhớ bằng tay nếu bạn sử dụng cú pháp mảng vì nó được giải phóng khi nó nằm ngoài phạm vi. Mặt khác, calloc sẽ cấp phát bộ nhớ động vào thời gian chạy trên heap. Bạn sẽ phải tự giải phóng nó ngay khi bạn hoàn thành nó.

+0

http://gcc.gnu.org/onlinedocs/gcc/Variable-Length. html –

0

int array[variable]; 

không hợp lệ trong tiêu chuẩn C - bạn chỉ có thể xác định độ dài của một mảng với một hằng số. (chẳng hạn như

char name[] = "Nick"; 

ví dụ, không phải là độ dài khác nhau).

Như vậy, cần sử dụng bộ cấp phát bộ nhớ như calloc() nếu bạn muốn tạo một mảng có độ dài dựa trên biến số chương trình.

Đừng quên miễn phí().

+0

Đúng, không phải là độ dài thay đổi. Tôi đoán tôi nên đặt "năng động". Như trình biên dịch xác định bao nhiêu nên được phân bổ. – nmiller

+0

Có lẽ - nhưng "động" vẫn ngụ ý thời gian chạy cho tôi. Với việc khởi tạo từ một hằng số, kích thước của mảng được xác định tại thời gian biên dịch, không phải thời gian chạy. – HanClinto

+9

Nó là hợp lệ trong C99 cho một biến địa phương (tự động) - nó không hợp lệ như một khai báo biến bên ngoài (biến sẽ phải là một hằng số biên dịch-thời gian). –

8

Tôi đồng ý với ocdecio không cho phép

int array[variable] 

cho phép một số loại biến và biểu thức là kích thước mảng. Nhưng ngoài ra, mọi thứ được phân bổ với malloc và gia đình có thể được thay đổi kích thước bằng cách sử dụng realloc.

3

Sử dụng các mảng có kích thước biến trên ngăn xếp dưới dạng biến tự động (thay vì đống bằng cách sử dụng calloc/malloc/new/etc) không phải là ý tưởng tồi cho quá trình sẽ chạy trong một thời gian dài và sẽ cần tạo và tiêu diệt rất nhiều mảng nhỏ. Điều này là do ngăn xếp được đảm bảo không bao giờ bị phân mảnh, trong khi bộ nhớ có thể và sẽ bị phân mảnh.Nếu bạn đang viết chương trình cơ sở hoặc một dịch vụ cần chạy trong nhiều năm mà không dừng lại, bạn gần như bị cấm sử dụng malloc hoặc mới.

2

Dải tự động có độ dài thay đổi được cho phép trong ISO C99 và như một phần mở rộng GCC chấp nhận chúng ở chế độ C90 và trong C++. Vì vậy, không nên thiết lập bộ biên dịch flag -std = c99 hoặc -std = gnu99. Theo gương sẽ làm việc

#include<stdio.h> 

int main() 
{ 
    int n; 
    printf("\n\tEnter the number of digits: "); 
    scanf("%d", &n); 

    char str[n]; 
    for(int i=0; i < n; i++) { 
     scanf("%s", &str[i]); 
    } 

    printf("\n\tThe entered digits are: %s", str); 
return 0; 
} 

tôi garantee rằng :-)