Làm thế nào để mảng [100] = {0} đặt toàn bộ mảng thành 0?


140

Làm thế nào để trình biên dịch điền giá trị trong char array[100] = {0};? Điều kỳ diệu đằng sau nó là gì?

Tôi muốn biết làm thế nào trình biên dịch nội bộ khởi tạo.


1
Trong C hay C ++? Chúng là hai câu hỏi riêng biệt.
Toby Speight

Câu trả lời:


163

Đó không phải là phép thuật.

Hành vi của mã này trong C được mô tả trong phần 6.7.8.21 của đặc tả C ( bản nháp trực tuyến của thông số C ): đối với các phần tử không có giá trị được chỉ định, trình biên dịch khởi tạo con trỏ thành NULL và các loại số học về 0 ( và áp dụng đệ quy này cho tổng hợp).

Hành vi của mã này trong C ++ được mô tả trong phần 8.5.1.7 của đặc tả C ++ ( bản nháp trực tuyến của thông số C ++ ): trình biên dịch tổng hợp khởi tạo các phần tử không có giá trị được chỉ định.

Ngoài ra, lưu ý rằng trong C ++ (chứ không phải C), bạn có thể sử dụng danh sách trình khởi tạo trống, khiến trình biên dịch tổng hợp khởi tạo tất cả các phần tử của mảng:

char array[100] = {};

Đối với loại mã nào trình biên dịch có thể tạo khi bạn thực hiện việc này, hãy xem câu hỏi này: Tập hợp lạ từ khởi tạo mảng 0


Có phải tất cả các trình biên dịch C làm điều này? Tôi đã được tin rằng chỉ có Visual Studio làm điều này.
JFA

1
dự thảo trực tuyến của thông số kỹ thuật c ++ bị hỏng, bất cứ ai có liên kết mới?
Behrooz Karjoo

35

Việc thực hiện là tùy thuộc vào các nhà phát triển trình biên dịch.

Nếu câu hỏi của bạn là "điều gì sẽ xảy ra với khai báo như vậy" - trình biên dịch sẽ đặt phần tử mảng đầu tiên thành giá trị bạn đã cung cấp (0) và tất cả các phần tử khác sẽ được đặt thành 0 vì đó là giá trị mặc định cho các phần tử mảng bị bỏ qua.


Tôi không có nguồn, nhưng tôi khá chắc chắn rằng tôi đã đọc ở đâu đó rằng không có giá trị mặc định cho khai báo mảng; bạn nhận được bất cứ thứ gì rác đã ở đó. Không có ý nghĩa trong việc lãng phí thời gian để thiết lập các giá trị này khi bạn có khả năng ghi đè lên chúng bằng mọi cách.
Ryan Fox

10
Ryan, nếu bạn không đặt giá trị cho phần tử đầu tiên thì toàn bộ mảng không được khởi tạo và thực sự có chứa rác, nhưng nếu bạn đặt một giá trị cho ít nhất một phần tử của nó thì toàn bộ mảng sẽ được khởi tạo để các phần tử không xác định được khởi tạo hoàn toàn 0.
qrdl 10/03/2016

1
Đối với C ++, một danh sách khởi tạo trống cho mặc định mảng bị ràng buộc - khởi tạo tất cả các phần tử.
dalle

2
@NatanYellin Tôi đã nói điều này ở đâu không xác định? Xin vui lòng đọc câu trả lời đầy đủ trước khi bình luận và downvote.
qrdl

1
@qrdl Bạn nói đúng. Tôi hiểu nhầm ý kiến ​​của bạn về việc thực hiện. Thật không may, tôi không thể thay đổi phiếu bầu của mình bây giờ.
Natan Yellin

27

Nếu trình biên dịch của bạn là GCC, bạn cũng có thể sử dụng cú pháp sau:

int array[256] = {[0 ... 255] = 0};

Vui lòng xem http://gcc.gnu.org/onlinesocs/gcc-4.1.2/gcc/Designated-Inits.html#Designated-Inits và lưu ý rằng đây là một tính năng dành riêng cho trình biên dịch .


Chào mừng bạn kể từ khi bạn yêu cầu Tìm kiếm nhiều loại mánh khóe như vậy, tôi đã cung cấp
lakshmanaraj

1
Bạn chắc chắn có thể làm điều này nếu bạn chọn, nhưng có những nhược điểm rõ ràng khi dựa vào các tiện ích mở rộng dành riêng cho trình biên dịch như thế này.
Dan Olson

@Dan Olson, câu hỏi của anh ấy là hỏi về trình biên dịch cụ thể và do đó đã đăng bài này. Nếu bạn cảm thấy nó vô dụng, tôi sẽ xóa.
lakshmanaraj

5
Nó không vô dụng, thật thú vị. Sự cảnh báo chỉ xứng đáng được lưu ý.
Dan Olson

2
Những thứ như thế này khiến tôi quay trở lại SO và đọc nhiều hơn những câu trả lời hàng đầu ...
timday 10/03/2016

19

Nó phụ thuộc vào nơi bạn đặt khởi tạo này.

Nếu mảng tĩnh như trong

char array[100] = {0};

int main(void)
{
...
}

sau đó nó là trình biên dịch dự trữ 100 0 byte trong phần tách dữ liệu của chương trình. Trong trường hợp này, bạn có thể đã bỏ qua trình khởi tạo.

Nếu mảng của bạn là tự động, thì đó là một câu chuyện khác.

int foo(void)
{
char array[100] = {0};
...
}

Trong trường hợp này tại mỗi cuộc gọi của hàm foo, bạn sẽ có một bộ nhớ ẩn.

Mã ở trên tương đương với

int foo(void)
{ 
char array[100];

memset(array, 0, sizeof(array));
....
}

và nếu bạn bỏ qua trình khởi tạo, mảng của bạn sẽ chứa dữ liệu ngẫu nhiên (dữ liệu của ngăn xếp).

Nếu mảng cục bộ của bạn được khai báo tĩnh như trong

int foo(void)
{ 
static char array[100] = {0};
...
}

sau đó về mặt kỹ thuật là trường hợp tương tự như trường hợp đầu tiên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.