2010-04-10 35 views
7

sự khác biệt giữaSự khác nhau giữa alloca (n) và char x [n] là gì?

void *bytes = alloca(size); 

char bytes[size]; //Or to be more precise, char x[size]; void *bytes = x; 

... nơi kích thước là một biến mà giá trị chưa được biết rõ tại thời gian biên dịch là gì.

+1

Câu trả lời phụ thuộc nhiều vào việc 'kích thước' là hằng số biên dịch hay không. Là nó? – AnT

+0

không, kích thước là, cho tất cả các mục đích và mục đích, một đối số cho hàm –

+0

Điều đó không quan trọng. Apple, theo mặc định, sử dụng '--std = gnu99' hỗ trợ cả hai. 'alloca()' là một phần mở rộng của GNU, và mảng độ dài biến là một tính năng C99 tương thích tiêu chuẩn. –

Trả lời

13

alloca() không đòi lại bộ nhớ cho đến khi chức năng hiện tại kết thúc, trong khi mảng độ dài biến đổi lại bộ nhớ khi khối hiện tại kết thúc.

Nói cách khác:

void foo() 
{ 
    size_t size = 42; 
    if (size) { 
     void *bytes1 = alloca(size); 
     char bytes2[size]; 
    } // bytes2 is deallocated here 
}; //bytes1 is deallocated here 

alloca() thể được hỗ trợ (trong một thời trang) trên bất kỳ trình biên dịch C89, trong khi mảng chiều dài thay đổi đòi hỏi một trình biên dịch C99.

+2

@Billy: bộ nhớ được cấp phát bởi byte char [size] không được đảm bảo để được khai hoang vật lý ở cuối khối hiện tại; tuy nhiên truy cập sau khi khối hiện tại là không thể nữa. – Vlad

+0

Trình biên dịch nào thực hiện điều đó? –

+2

@Vlad: Về mặt kỹ thuật, tiêu chuẩn C đề cập rất ít về nơi mọi thứ thực sự cần được lưu trữ trên thực tế để tránh bất kỳ sự phụ thuộc nào có thể xảy ra trên một kiến ​​trúc cụ thể. Tuy nhiên, ngay cả khi một cái gì đó không có trong tiêu chuẩn một cách rõ ràng, ý nghĩa tiềm ẩn trong các kết quả tiêu chuẩn trong 99,9% các trình biên dịch thực hiện nó theo cách đó. –

0

Ở dạng thứ hai, size phải là một hằng số được biết để biên dịch thời gian.

+3

Không có trong C99. (15chars) –

+0

@Billy: Thật vậy. – Vlad

+0

Có thể, nhưng có nhiều khả năng OP đang đề cập đến các mảng chiều dài thay đổi, một phần của tiêu chuẩn C99. – rjh

6

Từ GNU documentation:

Space giao alloca tồn tại cho đến khi có chứa chức năng lợi nhuận. Không gian cho một mảng có độ dài thay đổi được deallocated ngay khi phạm vi của mảng tên kết thúc. (Nếu bạn sử dụng cả hai mảng chiều dài thay đổi và alloca trong cùng chức năng, deallocation của một mảng chiều dài thay đổi cũng sẽ deallocate bất cứ điều gì gần đây được phân bổ với alloca.)

Bên cạnh đó, alloca không phải là một hàm C chuẩn, để hỗ trợ không được đảm bảo trên tất cả các trình biên dịch. Các mảng chiều dài thay đổi là một phần của tiêu chuẩn C99, vì vậy bất kỳ trình biên dịch hỗ trợ C99 nào cũng nên thực hiện nó.

+0

Thậm chí nếu nó không được trình biên dịch của bạn hỗ trợ, thường có các phiên bản miền công cộng của 'alloca' có sẵn. –

+0

lưu ý rằng alloca() được quy định trong POSIX.1-2001 – martinkunev

5

Bên cạnh điểm Billy đã đề cập, alloca không chuẩn (không phải ngay cả trong C99).

0

Bên cạnh những điểm đã được bàn luận khi chính xác không gian được giải phóng, và liệu xây dựng được hỗ trợ ở tất cả, đó cũng là điều này:

  • Trong trường hợp alloca, bytes có một kiểu con trỏ.
  • Trong trường hợp [], bytes có loại mảng.

Sự khác biệt đáng chú ý nhất là ở những gì sizeof(bytes) là; cho một con trỏ nó là kích thước của con trỏ (sizeof(void *)) trong khi đối với một mảng nó là kích thước của không gian được phân bổ (sizeof(char) * size, trong đó = size cho trường hợp này kể từ sizeof(char) = 1).

(Ngoài ra, trong ví dụ của bạn, các loại yếu tố khác nhau;. Để được như vậy, đầu tiên nên được thay đổi để char *bytes = alloca(size))

0

Sự khác biệt lớn nhất là alloca không gọi nhà thầu hoặc hủy khi bạn đang sử dụng bộ nhớ làm biến lớp.

Sự khác biệt khác ít có khả năng được chú ý hơn, nhưng có thể trở nên rõ ràng trong một số lỗi thời gian chạy lạ trong một số trường hợp.

Các vấn đề liên quan