Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I properly initialize a C struct from C++?

I have the following code in a C++ file:

#include <sys/socket.h>

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

When I compile with g++ using -Wall -Wextra, I get warnings:

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

My problem is this: I can't explicitly initialize all the fields, because I don't know what fields will exist (cross-platform) in a struct msghdr. The struct doesn't have a default constructor, since it's a C struct. I was under the impression that the = {0} form led to zero-initialization of all fields (which would be fine for me), but the g++ error message suggests not.

What are my options here?

like image 801
Tim Martin Avatar asked Jan 24 '11 13:01

Tim Martin


People also ask

How do you initialize a struct in C?

Structure members can be initialized using curly braces '{}'.

How do you initialize a structure?

An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign ( = ).

Does C initialize structs to 0?

You don't have to initialise every element of a structure, but can initialise only the first one; you don't need nested {} even to initialise aggregate members of a structure. Anything in C can be initialised with = 0 ; this initialises numeric elements to zero and pointers null.

How do you initialize in C?

Different ways of initializing a variable in Cint a, b; a = b = 10; int a, b = 10, c = 20; Method 5 (Dynamic Initialization : Value is being assigned to variable at run time.)


2 Answers

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

The g++ -Wextra warning level is IMHO not very useful.

The code that you have is also formally OK for a "C struct", in standardeese known as POD (Plain Old Data). But your code explicitly initializes first member with 0. That won't necessarily work for an aggregate that isn't POD, e.g. with a std::string as first member, while the pure {} will work also for that.

In passing, often a POD like the one you're dealing with has a byte count as first member, and then you can do like …

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

Perhaps add a STATIC_ASSERT that the byte count member is first (at offset 0).

Cheers & hth.,

like image 155
Cheers and hth. - Alf Avatar answered Sep 21 '22 17:09

Cheers and hth. - Alf


This should work:

memset(&msg, 0, sizeof(msg));
like image 43
Eric Fortin Avatar answered Sep 17 '22 17:09

Eric Fortin