Structural aggregate initialization with fewer caveats, why does it initialize everything?

If I have a general linux structure like:

struct sockaddr_in
{
  sa_family_t    sin_family;   
  in_port_t      sin_port;     
  struct in_addr sin_addr;     

  unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int)
                        - sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero        __pad

      

and I am doing aggregate initialization:

struct sockaddr_in my_addr = { 0 };

      

how come this initializes each member to 0?

I mean: the documentation says:

If the number of initializer clauses is less than the number of members, or the initializer clauses are completely empty, the remaining members are initialized with their sliding or equal initializers if provided in the class definition, and otherwise (starting in C ++ 14) empty lists that perform value initialization.

to simplify: why does this code print 0?

struct sockaddr_in my_addr = {2, 2}; // initialize sin_family and sin_port to 2, everything else value-initialized

my_addr = {0};

std::cout << my_addr.sin_port; // Why is this 0?

      

+3


source to share


2 answers


This is documented in the C ++ 14 <-100> List-initialization draft , which says:

List-initialization of an object or reference of type T is defined as follows:

and includes:

If T is an aggregate, aggregate initialization (8.5.1) is performed.

and has the following example:



struct S2 {
    int m1;
    double m2, m3;
}
S2 s21 = { 1, 2, 3.0 }; // OK
S2 s22 { 1.0, 2, 3 }; // error: narrowing
S2 s23 { }; // OK: default to 0,0,0

      

and 8.5.1

Aggregates, which says:

If the list contains fewer initializer clauses than there are members in the aggregate, then each member not explicitly initialized shall be initialized from a sliding or equal-initializer or, if there is no brace-or-equalinitializer, from an empty initializer list (8.5.4). [Example:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };

      

initializes ss.a with 1, ss.b with "asdf", ss.c with an expression like int {} (ie 0)

Note, 8.5.4

slightly different in C ++ 11, it says:

List-initialization of an object or reference of type T is defined as follows:

  • If there are no elements in the initializer list and T is a type class with a default constructor, the object is value-initialized.

  • Otherwise, if T is an aggregate, aggregate initialization (8.5.1) is performed.

+2


source


how come this initializes each member to 0?

Because what C does when initializing structs, and C ++ does the same for aggregate initialization for compatibility.

C does this because it's more convenient (usually for the ones you want for members for which you don't explicitly value them) and safer (it doesn't leave dangerously uninitialized variables lying around).



If you really want the rest of the structure members to remain uninitialized, you can do it like this:

struct sockaddr_in s; // entirely uninitialized
s.sin_family = 0;     // only initialize one member

      

+1


source







All Articles