2011-01-24 52 views
7

Tôi có đoạn code sau đây trong một ++ tập tin C:Tôi nên khởi tạo đúng cấu trúc C từ C++ như thế nào?

#include <sys/socket.h> 

// ... 
void someFunc() { 
    struct msghdr msg = {0}; // <<< Uninitialized member here 
} 

Khi tôi biên dịch với g++ sử dụng -Wall -Wextra, tôi nhận được cảnh báo:

error: missing initializer for member 'msghdr::msg_namelen' 
...same for several other fields 

Vấn đề của tôi là thế này: Tôi không thể dứt khoát khởi tạo tất cả các trường, bởi vì tôi không biết trường nào sẽ tồn tại (đa nền tảng) trong một số struct msghdr. Cấu trúc không có hàm tạo mặc định vì nó là cấu trúc C. Tôi đã theo ấn tượng rằng hình thức = {0} dẫn đến zero-khởi của tất cả các lĩnh vực (trong đó sẽ là tốt cho tôi), nhưng thông điệp g++ lỗi cho thấy không.

Tùy chọn của tôi ở đây là gì?

+0

thể trùng lặp của [Tại sao trình biên dịch ném cảnh báo này: "thiếu initializer"? Không cấu trúc khởi tạo?] (Http://stackoverflow.com/questions/1538943/why-is-the-compiler-throwing-this-warning-missing-initializer-isnt-the-stru) – ergosys

Trả lời

8
void someFunc() 
{ 
    msghdr msg = {}; // <<< All members zero-initialized 
} 

Các g ++ -Wextra mức cảnh báo là IMHO không phải là rất hữu ích.

Các mã mà bạn có cũng chính thức bật đèn xanh cho một "C struct", trong standardeese gọi là POD (Plain Old dữ liệu). Tuy nhiên, mã của bạn sẽ khởi tạo thành viên đầu tiên một cách rõ ràng bằng 0. Điều đó không nhất thiết phải hoạt động đối với tổng hợp không phải là POD, ví dụ: với một std::string như thành viên đầu tiên, trong khi tinh khiết {} sẽ làm việc cũng vì điều đó.

Trong qua, thường là một POD như một trong những bạn đang làm việc với có số byte như thành viên đầu tiên, và sau đó bạn có thể làm như & hellip;

void foo() 
{ 
    SomePODStruct o = {sizeof(o)}; // The other members zero-initialized. 
} 

Có thể thêm STATIC_ASSERT thành viên đếm byte đầu tiên (tại offset 0).

Cheers & hth,

+1

Tôi không đồng ý với câu _ Mức độ cảnh báo g ++ -Wextra không phải là rất hữu ích_. – peoro

+1

@peoro: OK. Tôi đã thêm một "IMHO".:-) –

+0

Cảm ơn Alf đầu vào, rất tốt khi biết rằng đó là '-Wextra' bị hỏng và không phải là sự hiểu biết của tôi về C++ :-) –

4

này nên làm việc:

memset(&msg, 0, sizeof(msg)); 
+0

sửa chữa lỗi đánh máy của bạn và Tôi sẽ loại bỏ câu trả lời của tôi, bạn đánh bại tôi để nó bằng giây! :) – Nim

1

Nếu bạn không thể sống với các cảnh báo và/hoặc không muốn vô hiệu hóa các cảnh báo, sau đó tôi nghĩ rằng nó sẽ phải khởi động rõ ràng qua ví dụ memset:

memset(&msg, 0, sizeof(msg)); 
0

có lẽ nếu bạn không muốn sử dụng constructor mặc định, bạn chỉ có thể sử dụng chức năng tiền xử lý như sau:.

#ifdef LINUX 
//init for linux 
#endif 

#ifdef WINDOWS 
//init for windows 
#endif 

và vân vân

+0

Tôi xin lỗi, tôi không hiểu làm thế nào điều này sẽ khởi tạo cấu trúc. Định nghĩa struct nằm ngoài tầm kiểm soát của tôi (nằm trong 'socket.h'). Bạn có thể đưa ra một ví dụ về việc khởi tạo cấu trúc sẽ trông như thế nào trong giải pháp được đề xuất của bạn? –

+0

Tôi có nghĩa là bạn biết cấu trúc trông như thế nào cho mỗi nền tảng. Và bạn có thể khởi tạo nó cho mỗi nền tảng bởi vì bạn biết tất cả các lĩnh vực. Vì vậy, nếu một nơi nào đó trong ứng dụng, bạn sẽ viết ví dụ #define LINUX sau đó #ifdef LINUX một phần sẽ được thêm vào bởi preprocessor để mã và thực hiện. Trong trường hợp này, chức năng của bạn sẽ khác nhau đối với nền tảng khác nhau. http://stackoverflow.com/questions/2989810/which-cross-platform-preprocessor-defines-win32-or-win32-or-win32 - có thể hữu ích – Andrew

+0

OK, có ý nghĩa, cảm ơn vì đã làm rõ. –

2

Lá cờ cảnh báo cụ thể gây ra điều này là -Wmissing-field-initializers, được bật như một phần của -Wextra. Cách đơn giản nhất để tránh cảnh báo (không có thật) này là sử dụng -Wno-missing-field-initializers.

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