2015-08-25 13 views
9

Tôi đã có ấn tượng rằng các khai báo mảng có kích thước biến không thể thực hiện được trong C89. Tuy nhiên, khi biên soạn với clang -ansi Tôi có thể chạy mã sau:Sử dụng sizeof() trong khai báo mảng trong C89

double array[] = { 0.0, 1.0, 2.0, 3.0, 4.0 }; 
double other_array[sizeof(array)] = { 0.0 }; 

Điều gì đang xảy ra ở đây? Có phải đó không được coi là khai báo mảng có kích thước biến không?

+0

whaoppps, editied –

+1

Không có mảng kích thước biến trong C89, vì vậy nó không thể được coi là một khai báo mảng kích thước biến. . –

Trả lời

5

Đó là bởi vì kết quả của sizeof điều hành là liên tục biểu, vì vậy nó không đủ điều kiện cho VLA, giống như khai báo như sau:

int other_array[5]; 

không thể mảng chiều dài thay đổi một trong hai. Từ C11 (N1570) §6.6/p6 biểu thức hằng số (tôi nhấn mạnh đi về phía trước):

Một số nguyên biểu thức hằng117) sẽ có kiểu số nguyên và có trách nhiệm chỉ có toán hạng đó là hằng số nguyên , hằng số liệt kê, hằng số ký tự, sizeof biểu thức có kết quả là số nguyên hằng số, biểu thức _Alignof và hằng số thả nổi là toán hạng ngay lập tức của phôi.

Vì lý do đầy đủ, nhà điều hành sizeof không phải lúc nào cũng dẫn đến biểu thức liên tục, mặc dù điều này chỉ ảnh hưởng đến tiêu chuẩn sau C89 (trong VLA C11 đã được thực hiện tùy chọn). Đề cập đến §6.5.3.4/p2 Các sizeof_Alignof khai thác:

Nếu kiểu của toán hạng là một loại mảng chiều dài thay đổi, các toán hạng được đánh giá; nếu không, toán hạng không được đánh giá và kết quả là hằng số nguyên.

3

Trước tiên, hãy xem tiêu chí cho một mảng (không phải là) một VLA. C11 doc, chương §6.7.6.2,

[...] Nếu kích thước là một số nguyên không đổi biểu và các loại nguyên tố có một kích thước không đổi được biết, loại mảng không phải là một biến chiều dài mảng loại ; [...]

Đến với trường hợp của bạn, sizeof là toán tử biên dịch, vì vậy nó tạo ra giá trị được coi là biểu thức hằng số biên dịch theo thời gian. Định nghĩa mảng có kích thước được chỉ định dưới dạng biểu thức hằng số thời gian biên dịch không phải là VLA. Vì vậy, trong mã của bạn,

int other_array[sizeof(array)] 

không phải là VLA.

Về kết quả sizeof điều hành, từ C11, chương §6.5.3.4, (nhấn mạnh tôi)

Nhà điều hành sizeof mang lại kích thước (tính theo byte) của toán hạng của nó, có thể là một biểu thức hoặc tên được ghi trong ngoặc đơn. [...] nếu không, toán hạng không được đánh giá và kết quả là hằng số nguyên.

+2

Trong C11 'sizeof' không phải là" toán tử thời gian biên dịch "và đôi khi không tạo ra biểu thức liên tục. (Mặc dù OP đã hỏi về C89) –

8

Trong ANSI C89 còn được gọi là ISO C90, các nhà điều hành sizeof mang lại một hằng số nguyên, đó là thích hợp cho kích thước mảng. Ví dụ, các cuộc gọi chức năng thì không.

Tôi muốn thêm một nhận xét khác vì tôi cho rằng mã như có vấn đề có thể bị bỏ qua.

Nếu other_array được khai báo là

double other_array[sizeof(array)]; 

nó sẽ không có cùng một số yếu tố, cũng không phải cùng kích thước (mà sẽ chỉ là đúng đối với mảng của char) như array[]. Nếu mục đích là để khai báo một mảng thứ hai với cùng một số nguyên tố (không phân biệt loại), sử dụng này:

double other_array[sizeof(array)/sizeof(*array)]; 
+1

Tại sao lại là downvote? – Jens

+3

Không phải của tôi downvote, nhưng đây không phải là một câu trả lời cho câu hỏi. Đây phải là một bình luận. –

+0

@JensGustedt Đủ công bằng. Nhưng tôi đã cố gắng thực sự hiểu * những gì mã được cho là đạt được, xem nhiều hơn câu hỏi kỹ thuật, khám phá lý do tại sao ai đó muốn một mảng khác số lượng các phần tử là một cho mỗi byte trong một mảng kép. Điều đó không đúng và các bình luận chỉ đơn giản là quá giới hạn khi nói đến định dạng. Có lẽ tôi nên lặp lại câu trả lời kỹ thuật lần thứ ba để phù hợp với kỳ vọng câu trả lời. – Jens

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