Khởi tạo cấu trúc thành 0


116

Nếu tôi có cấu trúc như thế này:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Cách dễ nhất để khởi tạo cấu trúc này thành 0 là gì? Những điều sau đây có đủ không?

myStruct _m1 = {0};

hoặc Tôi có cần buộc từng thành viên về 0 một cách rõ ràng không?

myStruct _m2 = {0,0};

Câu trả lời:


142

Đầu tiên là dễ nhất ( liên quan đến việc nhập ít hơn ), và nó được đảm bảo hoạt động, tất cả các thành viên sẽ được đặt thành 0[Tham khảo 1] .
Thứ hai là dễ đọc hơn.

Sự lựa chọn phụ thuộc vào sở thích của người dùng hoặc tùy chọn mà tiêu chuẩn mã hóa của bạn bắt buộc.

[Tham khảo 1] Tiêu chuẩn C99 tham chiếu 6.7.8.21:

Nếu có ít phần tử khởi tạo trong danh sách có dấu ngoặc nhọn hơn có các phần tử hoặc thành viên của một tập hợp hoặc ít ký tự hơn trong một chuỗi ký tự được sử dụng để khởi tạo một mảng có kích thước đã biết so với số phần tử trong mảng, thì phần còn lại của tổng hợp sẽ được khởi tạo ngầm giống như các đối tượng có thời lượng lưu trữ tĩnh.

Đọc tốt:
C và C ++: Khởi tạo một phần cấu trúc tự động


9
Ngoài ra, tôi đang sử dụng = {};Tuy nhiên tôi không chắc liệu điều này có hợp lệ hay không.
William Entriken

15
@FullDecent dấu ngoặc nhọn để khởi tạo là một phần mở rộng GNU.
a3f

2
@ alias65536 Câu hỏi được gắn thẻ C không phải C ++.
a3f

3
Tôi gặp lỗi: "thiếu dấu ngoặc nhọn xung quanh bộ khởi tạo [-Werror = Thiếu-dấu ngoặc nhọn]" có thể là do mảng thành viên: /
DrumM 14/02/18

3
@Edenia. Tôi không đồng ý. Tôi đã biết những gì foo = {0}có nghĩa là. Nếu tôi thấy foo = ZERO_FULL, tôi sẽ phải thốt lên vì định nghĩa của ZERO_FULL.
Andrew Bainbridge

32

Nếu dữ liệu là một biến tĩnh hoặc toàn cục, nó được điền bằng 0 theo mặc định, vì vậy chỉ cần khai báo myStruct _m;

Nếu dữ liệu là một biến cục bộ hoặc một vùng được phân bổ theo heap, hãy xóa dữ liệu đó bằng cách memset:

memset(&m, 0, sizeof(myStruct));

Các trình biên dịch hiện tại (ví dụ như các phiên bản gần đây của gcc) tối ưu hóa điều đó khá tốt trong thực tế. Điều này chỉ hoạt động nếu tất cả các giá trị 0 (bao gồm con trỏ rỗng và dấu phẩy động không) được biểu diễn dưới dạng tất cả các bit 0, điều này đúng trên tất cả các nền tảng mà tôi biết (nhưng tiêu chuẩn C cho phép triển khai trong đó điều này là sai; tôi không biết cách triển khai như vậy) .

Bạn có thể mã myStruct m = {};hoặc myStruct m = {0};(ngay cả khi thành viên đầu tiên của myStructkhông phải là một vô hướng).

Cảm giác của tôi là sử dụng memsetcho các cấu trúc cục bộ là tốt nhất và nó truyền đạt tốt hơn thực tế là trong thời gian chạy, một cái gì đó phải được thực hiện (trong khi thông thường, dữ liệu toàn cục và tĩnh có thể được hiểu là được khởi tạo tại thời điểm biên dịch, mà không có bất kỳ chi phí nào trong thời gian chạy) .


7
Không có gì đảm bảo rằng việc đặt tất cả các byte của struct thành 0sẽ tương đương với việc khởi tạo tất cả các thành viên struct 0. Trên nhiều nền tảng, điều này sẽ đúng, nhưng không phải trên toàn cầu.
Sander De Dycker

1
Bạn có thể chia sẻ một ví dụ, Sander? Sự tò mò thực sự. (Rõ ràng, không phổ biến sự thật không có nghĩa là có một dễ giải thích ngoại lệ, nhưng nếu có ...)
Steven Fisher

2
Các C tiêu chuẩn cho phép con trỏ null (hoặc một số điểm nổi zero) để được đại diện trong bộ nhớ bằng cái gì khác so với tất cả zero bit. Rất ít triển khai kỳ lạ đang làm điều đó (tôi không thể nêu tên bất kỳ).
Basile Starynkevitch

-1, bạn có thể thấy quá trình khởi tạo mà OP hỏi là xấu, nhưng nó chính xác là những gì được forseen theo tiêu chuẩn và có thể dễ dàng tối ưu hóa bởi tất cả các trình biên dịch. Khi đó, biểu mẫu {}không phải là C hợp lệ mà chỉ có sẵn trong C ++.
Jens Gustedt

7
@Steven: Tôi chỉ có thể nghĩ đến các nền tảng khó hiểu và / hoặc cũ. Câu hỏi thường gặp về C có danh sách các nền tảng có NULLcon trỏ không phải là tất cả các 0bit: c-faq.com/null/machexamp.html . Và sau đó có khả năng nền tảng không sử dụng IEEE 754 để biểu diễn các giá trị dấu phẩy động, mà sử dụng một số biểu diễn khác không có giá trị tất cả các 0bit 0.0- nhưng phải thừa nhận rằng tôi không biết nền tảng nào như vậy.
Sander De Dycker

19

Xem §6.7.9 Khởi tạo:

21 Nếu có ít bộ khởi tạo trong một danh sách được bao bởi dấu ngoặc nhọn hơn có các phần tử hoặc thành viên của một tổng thể hoặc ít ký tự hơn trong một chuỗi ký tự được sử dụng để khởi tạo một mảng có kích thước đã biết hơn là có các phần tử trong mảng, thì phần còn lại của tổng hợp sẽ được khởi tạo ngầm giống như các đối tượng có thời lượng lưu trữ tĩnh.

Vì vậy, có cả hai trong số họ làm việc. Lưu ý rằng trong C99, một cách khởi tạo mới, được gọi là khởi tạo được chỉ định cũng có thể được sử dụng:

myStruct _m1 = {.c2 = 0, .c1 = 1};

Đáng chú ý nhất là đây đã là C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Quan trọng đối với các mục tiêu xử lý tín hiệu cụ thể)
Tobias
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.