2012-03-05 25 views
15

Tôi biết trong C rằng tôi có thể làm như sau.Khởi tạo mảng C tại thời điểm khác với khai báo?

int test[5] = {1, 2, 3, 4, 5}; 

Bây giờ điều này chỉ hợp pháp khi khai báo mảng. Tuy nhiên tôi đã tự hỏi tại sao điều này là không hợp pháp để làm sau này? Nhưng sau đó trong chương trình nó không phải là hợp pháp để làm như sau.

test[5] = {10, 20, 30, 40, 50}; 

Hoặc tương tự. Tại sao điều này? Tôi biết nó không hợp pháp, và tôi không phàn nàn, nhưng ai đó có thể cho tôi một giải thích kỹ thuật hơn về lý do tại sao tôi không thể làm điều này? (nghĩa là không chỉ nói thông số C không cho phép nó hoặc một cái gì đó như thế)

Tôi giả định nó phải làm điều gì đó với thời gian khi bộ nhớ được cấp phát trên ngăn xếp cho mảng, vì vậy tại thời điểm đó C có thể tự động điền vào các giá trị của tôi, nhưng sau đó tại sao nó không thể làm điều đó sau này?

Thanks guys

+2

Vì vậy, nếu, giả thuyết, đó là trường hợp đó các tiêu chuẩn C chỉ sẽ không cho phép điều này (mặc dù nó sẽ là về mặt kỹ thuật có thể), chúng tôi sẽ phải làm một cái gì đó khác nhau lên thay vào đó? Hay bạn không muốn nhận được câu trả lời nào cả? Chỉ muốn chắc chắn. –

+1

@NiklasB .: Tôi đoán trong trường hợp đó, một người được cho là có lý trí để * tại sao * các nhà thiết kế ngôn ngữ C đã quyết định bỏ qua tính năng này sẽ là một câu trả lời. – Heinzi

+0

@Heinzi: Ồ, tôi hiểu rồi :) –

Trả lời

6

Điểm có ích là sử dụng int array[]={ }tuyên bốkhởi các đối tượng mà bạn đã tạo.

Bạn thực sự có thể gán giá trị cho một mảng sau nó đã được tuyên bố:

int array[5]; 
array[0] = 1, array[1] = 2, ... 

gì bạn đã làm được gán nhiều giá trị cho một nhập mảng duy nhất:

array[5] = {1,2,3,4,5}; // array[5] can only contain one value 

wo này uld là hợp pháp thay thế:

array[5] = 6; 

Hy vọng điều này có ý nghĩa. Chỉ là một câu hỏi về cú pháp.

+0

Ồ. Duhhh. Điều này thực sự đã giúp tôi. – kando

17

Không chỉ là mảng, bạn không thể cung cấp bộ khởi tạo cho bất kỳ thứ gì tại bất kỳ điểm nào khác ngoài định nghĩa. Đôi khi, mọi người đề cập đến tuyên bố thứ hai về một số thứ như int i; i = 0; là "khởi tạo i". Trong thực tế, nó gán cho i, trước đây giữ một giá trị không xác định bởi vì nó không được khởi tạo. Nó rất hiếm khi gây nhầm lẫn để gọi điều này "khởi tạo", nhưng theo như ngôn ngữ có liên quan không có initializer ở đó.

Chuyển nhượng và khởi tạo là những thứ riêng biệt cho ngôn ngữ, mặc dù cả hai đều sử dụng ký tự =. Mảng không thể gán.

Lý do mảng không thể chuyển nhượng được bao phủ ở nơi khác, ví dụ Why does C++ support memberwise assignment of arrays within structs, but not generally?. Câu trả lời ngắn gọn là "lý do lịch sử". Tôi không nghĩ có bất kỳ lý do kỹ thuật sát thủ nào khiến ngôn ngữ không thể thay đổi để cho phép gán mảng.

Có vấn đề phụ, ngữ pháp {1, 2, 3, 4, 5} là bộ khởi tạo, không phải là mảng theo nghĩa đen, và do đó không thể được sử dụng trong gán ngay cả khi các mảng được gán. Tôi không chắc chắn lý do tại sao C89 không có mảng chữ, có lẽ chỉ là không ai có xung quanh để yêu cầu họ. C99 giới thiệu cú pháp cho "chữ thường" nói chung và các mảng chữ cụ thể: (int[]) {1, 2, 3, 4, 5}.Bạn vẫn không thể gán cho một mảng từ nó.

3

Lưu ý rằng các hợp chất C99 đen cho phép bạn 'vượt qua mảng chức năng':

int your_func(int *test) 
{ 
    ...use test as an array... 
} 

void other_func(void) 
{ 
    int x = rand(); 
    if (your_func((int[]){ 0, 1, 2, x, 3, 4 }) > 0 || 
     your_func((int[]){ 9, x, 8, 7, 6, 5 }) > 0) 
     ...whatever... 
} 

Đây là không giống như tái khởi tạo một mảng với giá trị khác nhau, nhưng nó có thể là đủ gần đó nó hoạt động cho bạn.

0

Lý do cho điều đó ở bề mặt là các mảng hầu như ở mọi nơi được chuyển đổi thành con trỏ đến phần tử đầu tiên. Nếu bạn có hai mảng

double A[5]; 
double B[5]; 

trong một biểu thức như

A = B; 

cả hai đều đã được quy đổi con trỏ. Các A bên trái là đặc biệt không phải là một "lvalue", do đó bạn không thể gán cho nó.

Điều này nghe có vẻ như một lý do khập khiễng, nhưng tôi đoán là trong lịch sử nó chỉ xảy ra như thế. C (và C + + với nó) đã bị mắc kẹt trong một sự lựa chọn cú pháp sớm và nếu bạn muốn ở lại tương thích với mã di sản có lẽ không có nhiều cách ra khỏi nó.

+0

Bạn có bất kỳ trích dẫn nào cho rằng đây là lý do đằng sau quyết định thiết kế không? –

+0

@DavidHeffernan, không may là không, nếu không tôi sẽ cho nó. Trong C11, 6.7.1 p6 (cộng với chú thích cuối trang) vẫn cho thấy nghĩa vụ chuyển đổi thành con trỏ được lấy làm tính năng rất cơ bản của mảng. Tôi nghĩ rằng điều này là không may, trong phân công cụ thể và các nhà thiết kế sẽ là những tính năng tốt để có. Nhưng sẽ không thực tế nếu mong đợi một sự thay đổi như vậy xảy ra. –

+0

Nhưng không có trích dẫn thì đây là đầu cơ. Và tôi thực sự không thể thấy lý do kỹ thuật tại sao việc gán mảng không thể thực hiện được. –

2

Đây là Giải pháp

//Declaration 
int a[5]; 
int a_temp[5] = {1, 2, 3, 4, 5 }; 
memcpy(a, a_temp, sizeof(a)); 
//Now array a have values 1, 2, 3, 4, 5 
Các vấn đề liên quan