2

Since in C I can call the members of a struct by name (myStruct.myMember = ) I was wondering what I would do in C++ with those members that are not initialized. So as I understood, C++ does not support this kind of initialization:

static struct usb_endpoint_descriptor  fs_source_desc = {
        .bLength =      USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =  USB_DT_ENDPOINT,
        .bmAttributes =     USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =   __constant_cpu_to_le16 (64),
    };

But when I use correct syntax, how do I handle members that are not initialized? Let's say I want bDescriptorType uninitialized. Do I set it to NULL?

static struct usb_endpoint_descriptor fs_source_desc = {
    USB_DT_ENDPOINT_SIZE,
        NULL,
        USB_ENDPOINT_XFER_BULK,
        __constant_cpu_to_le16 (64)
};

Or is there any way in C++ to initialize the structure's members by their name?

tzippy
  • 6,458
  • 30
  • 82
  • 151
  • 6
    That's a really silly question title. Since you already know that the C language feature you're talking about isn't a feature of C++, why can't you give this post a more sensible title than printing a random error that you get when writing something that is not valid code? – Kerrek SB Jun 03 '13 at 12:23

3 Answers3

11

how do I handle members that are not initialized?

The feature you describe is called designated initializers and was introduced in C99. It is not supported by C++. All members that are not initialized explicitly are guaranteed to be set to zero (*).

Maybe you didn't consider it, but the same applies to regular struct initialization as well. Example:

typedef struct
{
  int a;
  int b;
} ab;

ab mystruct = { .a = 1 }; // a is 1, b is guaranteed to be 0
ab mystruct = { 1 };      // a is 1, b is guaranteed to be 0    

(The last example is also true for C++.)

This language rule is the reason why we can initialize all elements in a struct/array to zero by typing:

ab mystruct = { 0 };

because it actually means "set a to zero, and let then all other elements be implicitly initialized to zero".


(*) Formally, they are initialized as if they had static storage duration, i.e. data gets set to zero, pointers get set to NULL etc. C11 6.7.9/10.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thank you very much! Now I can phrase the title accordingly and also my source code!. – tzippy Jun 03 '13 at 14:44
  • *{}* would be ok in place of *{0}*, right? – Max Barraclough Jan 30 '22 at 21:12
  • @MaxBarraclough No, that's invalid syntax. – Lundin Jan 31 '22 at 07:26
  • @Lundin Thanks. I see that by default the GCC compiler allows it, but it's non-standard. There's a thread on this topic: https://stackoverflow.com/a/17589839/ – Max Barraclough Jan 31 '22 at 08:46
  • Thank you. To provide specific quote from C11 standard that claims that fields skipped are not left "uninitialized": `all subobjects that are not initialized explicitly [in initializer list] shall be initialized implicitly the same as objects that have static storage duration.` – Hi-Angel Jun 28 '23 at 09:57
  • …and for completeness: similar rule in C99 is mentioned at `6.7.8.19` – Hi-Angel Jun 28 '23 at 10:29
7

If you use C++, then use constructors. Init by NULL is more C-way really.

And no, there is no standard C++ way to use named parameters (something like boost::parameters may help, but there is no need to it here).

Your case may be something like

struct usb_endpoint_descriptor
{
   usb_endpoint_desctiptor(type bL, type bAttr, type wSize) :
   bLength(bL), bAttributes(bAttr), wMaxPacketSize(wSize) {}
   type bLength;
   type bDescriptorType;
   type bmAttributes;
   type wMaxPacketSize;
};

However, it's bad style to leave variables not-initialized in C++.

So, if you use C structure, you can

1) Write C++ wrapper.

2) Write derived class.

3) Initialize field, that you don't want to initialize with some default value.

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Thanks! The structs I am using are from the /usb/ch9.h header file. So there's no constructor available. – tzippy Jun 03 '13 at 12:33
  • 2
    @tzippy In C, if you give an explicit initializer for any member, the members for which no explicit initializer is given are initialized as if they were objects of static storage duration, that means with a type-appropriate value of 0. – Daniel Fischer Jun 03 '13 at 12:48
  • The sentiment, always prefer constructors in C++, is not true anymore with c++17 and c++20. There is more support for aggregate initialization, and it is encouraged. – Joshua Clayton Nov 19 '21 at 18:32
0

FYI, All of the previous answers were correct. there was no support for designated initializers in C++... until C++20.

C++20 added aggregate initializers in that version of the C++ standard. The syntax is different than C99 dot notation because, I guess the standard committee wanted the syntax to be more idiomatically Cplusplussesque.

Here is an on point stack overflow question Designated initializers in C++20

And here is a popular reference site. https://en.cppreference.com/w/cpp/language/aggregate_initialization

Joshua Clayton
  • 1,669
  • 18
  • 29